Hubungi dukungan

Kami membalas melalui e-mail, biasanya dalam dua hari.

Google reCAPTCHA memeriksa kiriman ini untuk mencegah penyalahgunaan; data dikirim ke Google. Skrip hanya dimuat saat formulir ini dibuka.

← Semua artikel

Pemeriksaan yang selalu bernilai benar

Ada 23 pernyataan UPDATE di layanan ini. Tepat satu di antaranya memeriksa apakah ia mengubah sesuatu. Pemeriksaan itu adalah:

'success' => $n->rowCount() >= 0

rowCount() mengembalikan 0 jika tidak ada baris yang cocok. Nol lebih besar dari atau sama dengan nol. Pemeriksaan ini lolos apa pun yang terjadi.

23 pernyataan UPDATE, satu di antaranya melihat hasilnya rowCount() >= 0 — lolos meskipun tidak ada yang cocok rowCount() > 0 di seluruh basis kode: 0 kali penghitung yang punya baris di tabel yang diperbarui: 4 dari 2.218 saat ini tidak ada yang rusak — karena alasan yang bukan baris ini

Untuk apa pernyataan ini

Pernyataan ini menyimpan sebuah kotak centang: apakah pemilik penghitung ingin menerima ringkasan mingguan lewat e-mail. Alamatnya disimpan di tabel terpisah, dan sebuah baris baru muncul di sana setelah seseorang mengklik tautan konfirmasi dalam e-mail yang ia minta. Empat penghitung memiliki baris seperti itu. Penghitung yang aktif ada 2.218.

Jadi, untuk 99,8% penghitung, UPDATE tidak cocok dengan apa pun. Endpoint menjawab success: true dan pengaturannya tidak tersimpan, karena tidak ada tempat untuk menyimpannya.

Komentar di atasnya benar

Tiga baris lebih atas, di fungsi yang sama:

“Hanya jika ada jalur balik yang sudah dikonfirmasi. Tanpa itu tidak ada alamat yang bisa dituju surat — dan kotak centang itu akan menjanjikan sesuatu yang tidak terjadi.”

Itu tepat sekali. Seseorang memikirkan kasus ini, memahaminya, dan menuliskan penalarannya. Lalu baris di bawahnya memakai >= padahal penalaran itu menuntut >.

Hal ini patut dicermati dengan jujur, karena penjelasan yang biasa — tidak ada yang memikirkannya — mudah diambil tetapi salah. Pemikirannya ada di berkas itu. Yang gagal adalah satu karakter, di tempat versi yang salah dan versi yang benar tampak sama persis sekilas dan berperilaku sama persis dalam setiap uji yang memiliki baris untuk diperbarui.

Tidak ada yang dibohongi

Inilah bagian yang mudah dihilangkan, dan menghilangkannya akan membuat tulisan ini lebih dramatis dan kurang benar.

Halaman tidak menampilkan kotak centang itu kecuali barisnya ada. Satu layar dari situ, di kode yang menggambar kotak pengaturan pemilik, tabel yang sama dikueri terlebih dahulu, dan seluruh blok dilewati jika kueri itu kembali kosong. Jadi pemilik penghitung tanpa alamat yang sudah dikonfirmasi tidak pernah melihat kontrol itu, tidak pernah mengkliknya, dan tidak pernah mendapat konfirmasi palsu.

Pemeriksaan yang rusak itu hanya dapat dicapai dengan memanggil endpoint secara langsung dengan token yang valid. Siapa pun yang melakukannya mendapat success: true tanpa pengaturan yang tersimpan. Itu cacat yang nyata, tetapi sempit.

Mengapa ini tetap patut dicatat

Fitur ini aman berkat sebuah pengaman yang tidak pernah dicatat siapa pun sebagai pengaman. Baris yang ada untuk membuatnya aman tidak membuatnya aman. Yang membuatnya aman adalah sebuah kondisi tampilan di fungsi lain, yang komentarnya menjelaskan mengapa kotak centang disembunyikan — bukan bahwa ada sesuatu yang bergantung pada kotak itu tetap tersembunyi.

Hapus atau susun ulang kondisi tampilan itu — hal yang wajar dilakukan saat merancang ulang panel pengaturan — maka cacat itu langsung terlihat, tanpa ada apa pun yang menghubungkan kedua perubahan tersebut. Keamanannya nyata, tetapi kebetulan, dan keamanan yang kebetulan adalah jenis yang lenyap saat mengerjakan hal lain yang tidak berkaitan.

Basis kode yang sama melakukannya dengan benar di berkas sebelahnya. Fungsi padanan untuk cincin web menanyakan apakah barisnya ada, mengembalikan false jika tidak ada, dan sama sekali tidak menjalankan pembaruan. Tabel itu saat ini tidak berisi satu baris pun, jadi fungsi tersebut mengembalikan false setiap kali dipanggil, dan itulah jawaban yang benar.

Pola umumnya

Sebuah UPDATE yang tidak cocok dengan baris mana pun bukanlah galat di basis data mana pun. Itu pernyataan yang berhasil tetapi tidak melakukan apa-apa, dan setiap lapisan di atasnya akan melaporkan keberhasilan kecuali ada yang bertanya. Dua puluh dua pernyataan di sini tidak bertanya, dan bagi sebagian besar di antaranya itu tidak masalah: pernyataan-pernyataan itu memperbarui baris yang keberadaannya sudah dibuktikan oleh permintaan.

Satu-satunya yang perlu bertanya, bertanya dengan cara yang tidak mungkin gagal. rowCount() >= 0 bukanlah pemeriksaan yang lemah, melainkan ketiadaan pemeriksaan yang berkostum pemeriksaan — dan itu lebih buruk daripada tidak ada pemeriksaan sama sekali, karena orang berikutnya yang membaca fungsi itu melihat ada hasil yang diperiksa lalu berhenti mencari.

Frasa rowCount() > 0 muncul nol kali di basis kode ini. Angka itulah yang membuat salah ketik satu karakter layak dijadikan tulisan: bukan karena pernah sekali ditulis salah, melainkan karena tidak ada satu pun contoh yang benar di mana pun sebagai pembanding.

Diperbaiki pada 28 Agustus 2026. Endpoint itu kini menanyakan apakah barisnya ada sebelum memperbarui, seperti yang sudah dilakukan fungsi cincin web di berkas sebelahnya, dan menjawab false jika tidak ada. Perbaikan satu karakter yang tampak jelas — membandingkan dengan lebih-besar-dari-nol — diukur terlebih dahulu lalu ditolak: driver melaporkan baris yang berubah, bukan baris yang cocok, sehingga menyetel kotak centang ke nilai yang sudah dimilikinya tidak mengubah apa pun, dan versi itu akan melaporkan kegagalan untuk operasi yang sebenarnya baik-baik saja. Kedua versi itu salah, ke arah yang berlawanan.

Iklan