Topik temu duga representatif

Temu Duga Pengekodan: Bagaimana anda menukar kegagalan fuzz Go kepada korpus regresi?

PengekodanSukar
Pasukan Editorial Offer.ccDiterbitkan Dikemas kini

Soalan

Reka ujian fuzz Go untuk penghurai (parser) input. Mulakan dengan korpus benih, nyatakan invarians, dan terangkan bagaimana input gagal yang diminimumkan menjadi ujian regresi di bawah go test biasa.

Soalan dan senario yang sesuai

Anda menyelenggara penghurai (parser) input Go yang kadangkala menerima Unicode, bait terpotong atau panjang ekstrem dalam pengeluaran. Terangkan cara mereka bentuk sasaran fuzz testing.F, memilih benih, menyatakan sifat apabila output tepat tidak diketahui, dan mengekalkan kegagalan sebagai regresi selepas pembetulan.

Ini sesuai untuk peranan bahagian belakang (backend), infrastruktur dan alat ujian (test-tooling). Panduan temu duga teknikal Microsoft secara jelas menilai ujian, sempadan dan implikasi keselamatan; panduan SDE Amazon menyenaraikan pengaturcaraan dan topik perisian teras. Isyarat temu duga ialah gelung kejuruteraan, bukan menghafal arahan.

Perkara yang diuji oleh penemu duga

  • Membezakan nilai jangkaan ujian contoh daripada sifat ujian fuzz.
  • Memilih sasaran pantas tanpa kesan sampingan luaran.
  • Menerangkan korpus benih, panduan liputan (coverage guidance), peminimuman dan main semula (replay).
  • Mengendalikan UTF-8 tidak sah, input kosong, input bersaiz besar dan had sumber.
  • Menghubungkan penemuan, diagnosis, pembaikan, pelaksanaan semula dan korpus yang dikomit.

Jawapan yang lemah menyatakan "jana input rawak." Jawapan yang kukuh menamakan invarians, arahan, laluan kegagalan dan pembahagian CI.

Penjelasan sebelum menjawab

  1. Adakah input penghurai ialah string, []byte atau beberapa medan? Ini menentukan hujah fuzz dan pengekodan korpus.
  2. Input tidak sah manakah yang merupakan ralat yang dijangkakan? Kontrak ralat mengubah asersi.
  3. Apakah belanjawan sumber bagi setiap panggilan? Input yang perlahan mungkin merupakan isyarat penafian perkhidmatan (denial-of-service).
  4. Adakah kita mencari panik, pepijat semantik atau regresi keserasian? Setiap satu memerlukan sifat dan benih yang berbeza.

Rangka kerja jawapan 30 saat

Saya bermula dengan sifat yang boleh disahkan, seperti "pengekodan selepas penghuraian mengekalkan struktur yang sama" atau "input tidak sah mengembalikan ralat terkawal." Saya menambah kes sempadan sebenar dengan f.Add, kemudian memastikan f.Fuzz kekal pantas, deterministik dan bersempadan. go test biasa menjalankan benih dan kegagalan yang disimpan; tugas CI yang berasingan menjalankan go test -fuzz dengan belanjawan masa. Go meminimumkan input yang gagal ke dalam testdata/fuzz/<name>. Selepas membetulkan punca utama, saya memainkan semula input tersebut, menjalankan suite ujian penuh dan mengkomit korpus supaya penemuan itu menjadi kekangan regresi.

Jawapan mendalam langkah demi langkah

1. Mulakan dengan sifat, bukan jawapan yang dijangkakan

Untuk penghurai, gunakan sifat ulang-alik (round-trip): Encode(Parse(x)) harus mewakili x selepas penormalan. Untuk transformasi rentetan, gunakan keidempoteman (idempotence), pengekalan panjang atau kesahan UTF-8. Benarkan penormalan yang ditentukan; jangan silap menganggap susun atur bait sebagai kontrak.

2. Bina sasaran fuzz yang bersempadan

go
func FuzzParseRoundTrip(f *testing.F) {
    f.Add([]byte("name=alice"))
    f.Add([]byte{})
    f.Fuzz(func(t *testing.T, input []byte) {
        t.Helper()
        if len(input) > 1<<20 {
            t.Skip()
        }
        got, err := Parse(input)
        if err != nil {
            return
        }
        again, err := Parse(Encode(got))
        if err != nil || !Equal(got, again) {
            t.Fatalf("round trip failed: %v", err)
        }
    })
}

Jenis dan susunan f.Add mesti sepadan dengan panggilan balik (callback). Sasaran tidak boleh menulis fail, memanggil rangkaian atau bergantung pada masa; jika tidak, fuzzing selari menghasilkan kegagalan yang tidak boleh dihasilkan semula.

3. Benihkan sempadan perniagaan

Benih harus merangkumi versi protokol, nilai kosong, medan pendua, teks bukan ASCII, pemotongan dan sampel pengeluaran yang telah disanitasi. Go menjalankan benih semasa ujian biasa, jadi setiap benih mestilah murah dan stabil.

4. Bahagikan mod pelaksanaan

Sebelum komit, jalankan go test -run=FuzzParseRoundTrip untuk menyemak benih. Tugas khusus boleh menjalankan go test -fuzz=FuzzParseRoundTrip -fuzztime=10s. Bendera masa menghadkan penerokaan; CI menguruskan keselarian dan belanjawan pakej dan bukannya kod pengeluaran.

5. Main semula dan diagnosis input yang diminimumkan

Go meminimumkan input yang masih mencetuskan kegagalan dan menulisnya di bawah testdata/fuzz/FuzzParseRoundTrip/. Main semula dengan go test -run=FuzzParseRoundTrip/<id>, kemudian kelaskan punca utama: asersi, panik, kehabisan sumber atau ketidakdeterministikan ujian. Sampel harus menerangkan pepijat, bukan menjadi gumpalan (blob) yang legap.

6. Jadikan pembaikan kekal

Main semula kegagalan selepas pembetulan, kemudian jalankan semua go test. Kegagalan yang disimpan juga berjalan tanpa -fuzz, jadi semak korpus untuk rahsia, penyuntingan (redaction) dan had saiz sebelum mengkomitkannya.

7. Ukur kualiti fuzz

Jika liputan berhenti berkembang, tambah benih berstruktur atau tingkatkan penjanaan dan bukannya hanya menambah tempoh masa. Kegagalan tamat masa (timeout) yang kerap memerlukan input yang lebih kecil atau pengasingan laluan yang mahal; anggap ia sebagai kecacatan prestasi. Kadar penemuan yang menurun bukanlah bukti ketepatan.

Contoh jawapan berkualiti tinggi

Saya mentakrifkan fuzzing berdasarkan sifat yang boleh dihasilkan semula, bukan hasil perniagaan yang dijangkakan untuk setiap input rawak. Untuk penghurai, input yang sah harus dihuraikan dan dikodkan semula kepada struktur yang sama; input yang tidak sah harus mengembalikan ralat terkawal dan tidak sekali-kali panik. Saya membenihkan input kosong, saiz maksimum yang diterima, medan pendua, Unicode dan kes pengeluaran yang disanitasi. Sasarannya adalah bersempadan dan bebas daripada kesan sampingan. Pembangun menjalankan go test -run=FuzzX; CI meneroka dengan -fuzztime yang tetap. Apabila Go menulis kegagalan yang diminimumkan, saya memainkannya semula, mengenal pasti punca utama, membetulkan pelaksanaan, menjalankan ujian biasa serta fuzzing, dan mengkomit testdata/fuzz/FuzzX. Satu penemuan kemudian menjadi semakan regresi pada setiap perubahan.

Kesilapan biasa

  • Menganggap fuzzing sebagai beban rawak → tiada orakel wujud → takrifkan invarians dan kontrak ralat terlebih dahulu.
  • Memanggil perkhidmatan langsung dari sasaran → rangkaian dan keadaan menjadikan kegagalan tidak konsisten (flaky) → gunakan palsu deterministik (deterministic fake).
  • Menjalankan kegagalan yang disimpan hanya dalam mod fuzz → pembaikan boleh mengalami regresi → simpannya dalam testdata/fuzz.
  • Menerima input tanpa had → satu kes menggunakan belanjawan → kuat kuasakan had dan rekod kes yang dilangkau.
  • Mengkomit setiap kes yang dijana → hingar dan pertambahan repositori → simpan kes yang menghasilkan semula pepijat atau meliputi cabang utama.

Soalan susulan dan respons

Adakah asersi ulang-alik (round-trip) terlalu ketat apabila penghuraian menormalkan input?

Ya. Bandingkan AST yang dinormalkan atau set medan dan nyatakan perbezaan susunan, ruang kosong atau huruf besar/kecil yang sengaja diabaikan.

Bolehkah sampel gagal yang mengandungi rahsia pengguna dikomit?

Tidak. Semak kelayakan dan data peribadi, sunting (redact), dan sahkan sampel yang disunting masih gagal. Jika ia tidak boleh dikomit dengan selamat, kekalkan pembiakan dalaman yang terkawal dan serahkan padanan sintetik.

Belanjawan CI ialah lima minit. Bagaimanakah fuzzing harus disesuaikan?

Jalankan benih dan kegagalan yang diketahui pada setiap binaan. Hadkan penerokaan mengikut masa, pakej dan sumber; rekodkan tamat masa dan bukannya melangkaunya secara senyap.

Bagaimana anda tahu sama ada ujian fuzz itu rosak?

Main semula kes yang diminimalkan dan periksa keadaan global, kerawakan dan pemasaan goroutine. Kemudian tulis ujian unit deterministik; jika ia tidak konsisten (flaky), betulkan pengasingan sebelum kod pengeluaran.

Bolehkah beberapa sasaran berkongsi korpus?

Kongsi logik penukaran hanya apabila format input dan semantik sepadan. Kekalkan direktori dan invarians yang berasingan supaya korpus satu sasaran tidak dapat menyembunyikan jurang liputan sasaran yang lain.

Sumber awam

Soalan berkaitan

Alat temu duga berkaitan

Gunakan Tangkapan Skrin untuk gesaan pengekodan

Tangkap soalan, kemudian selesaikan kekangan, penyelesaian, kod, kes pinggir dan kerumitan mengikut urutan.

Lihat alat