Mengapa bash bahkan menguraikan / menjalankan hal-hal yang dimasukkan ke dalam variabel lingkungan?

9

The SHELLSHOCK bug di bash bekerja dengan cara variabel lingkungan. Jujur saya terkejut oleh fakta bahwa ada fitur seperti:

"meneruskan definisi fungsi melalui env vars"

Oleh karena itu pertanyaan ini sementara mungkin tidak diformulasikan dengan sempurna adalah untuk meminta contoh atau kasus di mana akan diperlukan untuk memiliki fitur ini?

Bonus. Apakah shell lain zsh, dash dll juga memiliki fitur ini?

humanityANDpeace
sumber
Ia menggunakan env vars untuk meneruskan definisi fungsi. Apa yang Anda maksud dengan "Mengapa itu tidak hanya membuat variabel lingkungan tersedia / dapat diakses?" ?
Anthon
@Anthon Terima kasih atas komentarnya. Mungkin saya harus lebih jelas dan ulangi. Untuk alasan apa diperlukan untuk dapat meneruskan definisi fungsi melalui env vars?
humanityANDpeace
1
Saya tidak 100% yakin tetapi saya berpikir bahwa itu adalah cara GNU parallelmendapatkan definisi fungsi yang terdistribusi jika ia memanggil beberapa instance bash. Jika tidak dengan cara itu harus menulis yang ada di file, bahwa setiap contoh dipanggil membaca dan kemudian Anda harus berurusan dengan masalah seperti kapan file itu dapat dihapus.
Anthon
2
utas ini memiliki beberapa sejarah. fungsi yang diekspor, meskipun, gila . Jika Anda ingin shell baru untuk mewarisi perintah shell yang dapat dieksekusi Anda .dotsumber file yang sama dengan shell lama. Itulah yang dilakukan - dan itu masuk akal - atau Anda memberi makan shell baru file tersebut sebagai input saat execing. setelah dibaca setelah file di-cache oleh kernel.
mikeserv
@ mikeserv Apakah saya mengerti benar, bahwa sebagian besar shellshock terkait dengan fitur ini yang tidak begitu penting?
humanityANDpeace

Jawaban:

4

Ketika skrip memanggil skrip lain, variabel skrip induk dapat diekspor, dan kemudian mereka akan terlihat di skrip anak. Mengekspor fungsi adalah generalisasi yang jelas: mengekspor fungsi dari orang tua, membuatnya terlihat pada anak.

Lingkungan adalah satu-satunya cara yang nyaman bagi suatu proses untuk memberikan data yang sewenang-wenang kepada anak-anaknya. Data harus diolah menjadi string yang tidak mengandung byte nol, yang tidak menyulitkan fungsi shell. Ada metode potensial lainnya, seperti blok memori bersama atau file sementara yang dikirimkan melalui deskriptor file, tetapi ini dapat menyebabkan masalah dengan program perantara yang tidak tahu apa yang harus dilakukan dengan mereka atau akan menutupnya. Program berharap berjalan di lingkungan yang berisi variabel yang tidak mereka ketahui atau pedulikan, sehingga mereka tidak akan menimpa atau menghapusnya.

Pilihan menggunakan nama fungsi sebagai nama variabel lingkungan adalah aneh. Untuk satu hal, itu berarti bahwa variabel yang diekspor bentrok dengan fungsi yang diekspor dengan nama yang sama.

Fungsi yang diekspor adalah fitur lama. Fungsi ditambahkan dalam shell Bourne di SVR2 , dan fungsi yang diekspor di shell Versi 8 dirilis pada tahun yang sama (1984). Dalam shell itu, variabel dan fungsi menggunakan namespace yang sama. Saya tidak tahu bagaimana fungsi ekspor berfungsi. The Heirloom shell didasarkan pada varian Bourne yang memiliki fungsi tetapi tidak ekspor mereka.

ATT ksh seharusnya mendukung fungsi ekspor, tetapi melihat sumbernya atau bermain dengannya, saya tidak dapat melihatnya, pada ksh93u.

env -i /usr/bin/ksh -c 'f=variable; f () { echo function; }; typeset -fx f; /usr/bin/env; ksh -c f'
_=*25182*/usr/bin/env
PWD=/home/gilles
SHLVL=1
A__z="*SHLVL
ksh: f: not found

Klon domain publik Ksh (pdksh, mksh), tanda hubung dan zsh tidak mendukung fungsi ekspor.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
1
Terima kasih! Jadi, tanpa fungsi ekspor fungsi fitur hilang, namun ada beberapa shell seperti dasbor, zsh dan pdksh dll yang tidak memiliki fungsi ini, apakah saya membaca ini dengan benar?
humanityANDpeace
Tetapi ketika saya mengekspor fungsi dalam bash, itu masuk ke variabel like BASH_FUNC_f%%=() { echo hi }. Mengapa bash mem-parsing variabel lingkungan lainnya? Mengapa itu bahkan diurai BASH_FUNC_g%%ketika saya hanya menelepon f? (Rupanya, pre-shellshock, variabel lingkungan baru saja dipanggil fatau g- tapi saya masih bertanya-tanya mengapa gakan diuraikan jika saya tidak pernah memanggil gskrip saya)
Metamorphic
@Met Ini harus melihat semua variabel lingkungan untuk mencari tahu mana yang merupakan definisi fungsi. Itu bisa menghafal fakta itu dan menghindari penguraian kode fungsi sampai pertama kali dibutuhkan, tetapi itu akan menjadi kompleksitas tambahan untuk keuntungan yang sangat sedikit. Lebih mudah memiliki hanya satu jenis fungsi dan bukan dua ("fungsi normal" dan "fungsi dari variabel lingkungan yang perlu sedikit penguraian").
Gilles 'SANGAT berhenti menjadi jahat'
Tidak jelas. Saya menyarankan bahwa hal yang jelas harus dilakukan adalah, ketika saya menjalankan sesuatu yang disebut f, (1) memeriksa fungsi shell yang disebut f, (2) memeriksa variabel lingkungan yang dipanggil f, dan mencoba menguraikannya, (3) periksa setiap PATHkomponen untuk dieksekusi disebut f. Bagaimana bisa mem-parsing setiap variabel lingkungan sebagai kode shell, pada startup shell, tampak seperti desain yang tidak terlalu rumit?
Metamorphic
@Metamorphic Anda menyarankan untuk menambahkan langkah lain yang harus dikerjakan di setiap perintah. Anda juga harus menambahkan langkah lain ketika mendefinisikan atau membatalkan fungsi (setelah itu unset -f foo, bash tidak boleh lagi mencari definisi fungsi foodi lingkungan), ketika mendaftar fungsi (bagaimana Anda menangani declare -fselain membaca semua variabel lingkungan?) , dan apa pun yang saya tidak pikirkan. Desain Anda hanya tampak lebih mudah karena Anda mengabaikan sebagian besar. Sebaliknya, melakukan segala sesuatu saat startup adalah sepotong kode dan setelah itu semuanya berfungsi.
Gilles 'SANGAT berhenti menjadi jahat'