|
| 1 | +--- |
| 2 | +title: Porting ke API Buffer.from() / Buffer.alloc() |
| 3 | +layout: docs.hbs |
| 4 | +--- |
| 5 | + |
| 6 | +# Porting ke `Buffer.from()`/`Buffer.alloc()` API |
| 7 | + |
| 8 | +## Pratinjau |
| 9 | + |
| 10 | +Panduan ini menjelaskan cara bermigrasi ke metode konstruktor `Buffer` yang aman. Migrasi memperbaiki peringatan penghentian berikut: |
| 11 | + |
| 12 | +> Konstruktor Buffer() dan new Buffer() tidak direkomendasikan untuk digunakan karena masalah keamanan dan penggunaan. Mohon gunakan metode konstruksi Buffer.alloc(), Buffer.allocUnsafe(), atau Buffer.from() yang baru. |
| 13 | +
|
| 14 | +- [Varian 1: Hilangkan dukungan untuk Node.js 4.4.x dan 5.0.0 — 5.9.x](#varian-1) (*direkomendasikan*) |
| 15 | +- [Varian 2: Gunakan polyfill](#variant-2) |
| 16 | +- [Varian 3: Deteksi manual, dengan pengaman](#variant-3) |
| 17 | + |
| 18 | +### Menemukan bit kode yang bermasalah menggunakan `grep` |
| 19 | + |
| 20 | +Jalankan saja `grep -nrE '[^a-zA-Z](Lambat)?Buffer\s*\(' --exclude-dir node_modules`. |
| 21 | + |
| 22 | +Ini akan menemukan semua tempat yang berpotensi tidak aman dalam kode Anda sendiri (dengan beberapa yang sangat tidak mungkin pengecualian). |
| 23 | + |
| 24 | +### Menemukan bit kode yang bermasalah menggunakan Node.js 8 |
| 25 | + |
| 26 | +Jika Anda menggunakan Node.js 8.0.0 (yang direkomendasikan), Node.js memperlihatkan beberapa opsi yang membantu menemukan potongan kode yang relevan: |
| 27 | + |
| 28 | +- `--trace-warnings` akan membuat Node.js menampilkan jejak tumpukan untuk peringatan ini dan peringatan lain yang dicetak oleh Node.js. |
| 29 | +- `--trace-deprecation` melakukan hal yang sama, tetapi hanya untuk peringatan penghentian. |
| 30 | +- `--pending-deprecation` akan menampilkan lebih banyak jenis peringatan penghentian. Secara khusus, ini akan menampilkan peringatan penghentian `Buffer()`, bahkan pada Node.js 8. |
| 31 | + |
| 32 | +Anda dapat mengatur flag ini menggunakan variabel lingkungan: |
| 33 | + |
| 34 | +```bash |
| 35 | +$ export NODE_OPTIONS='--trace-warnings --pending-deprecation' |
| 36 | +$ cat example.js |
| 37 | +'use strict'; |
| 38 | +const foo = new Buffer('foo'); |
| 39 | +$ node example.js |
| 40 | +(node:7147) [DEP0005] DeprecationWarning: The Buffer() and new Buffer() constructors are not recommended for use due to security and usability concerns. Please use the new Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() construction methods instead. |
| 41 | + at showFlaggedDeprecation (buffer.js:127:13) |
| 42 | + at new Buffer (buffer.js:148:3) |
| 43 | + at Object.<anonymous> (/path/to/example.js:2:13) |
| 44 | + [... more stack trace lines ...] |
| 45 | +``` |
| 46 | + |
| 47 | +### Menemukan bit kode yang bermasalah menggunakan linter |
| 48 | + |
| 49 | +Aturan ESLint [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) atau [node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) juga menemukan panggilan ke `Buffer()` API yang tidak digunakan lagi. Aturan-aturan itu termasuk dalam beberapa preset. |
| 50 | + |
| 51 | +Namun, ada kekurangannya, itu tidak selalu [bekerja dengan benar](https://github.com/chalker/safer-buffer#why-not-safe-buffer) saat `Buffer` ditimpa misalnya dengan polyfill, jadi disarankan adalah kombinasi dari ini dan beberapa metode lainnya dijelaskan di atas. |
| 52 | + |
| 53 | +## <!--variant-1-->Varian 1: Hilangkan dukungan untuk Node.js 4.4.x dan 5.0.0 — 5.9.x |
| 54 | + |
| 55 | +Ini adalah solusi yang direkomendasikan saat ini yang hanya menyiratkan overhead minimal. |
| 56 | + |
| 57 | +Jalur rilis Node.js 5.x tidak didukung sejak Juli 2016, dan jalur rilis Node.js 4.x mencapai Akhir Masa Pakainya pada April 2018 (→ [Jadwal](https://github.com/nodejs/Release#Release_schedule)). Ini berarti bahwa versi Node.js ini *tidak* akan menerima pembaruan apa pun, bahkan jika ada masalah keamanan, jadi penggunaan jalur rilis ini harus dihindari, jika memungkinkan. |
| 58 | + |
| 59 | +Apa yang akan Anda lakukan dalam kasus ini adalah mengonversi semua panggilan `New Buffer()` atau `Buffer()` untuk menggunakan `Buffer.alloc()` atau `Buffer.from()`, dengan cara berikut: |
| 60 | + |
| 61 | +- Untuk `Buffer(number) baru`, ganti dengan `Buffer.alloc(number)`. |
| 62 | +- Untuk `New Buffer(string)` (atau `new Buffer(string, encoding)`), ganti dengan `Buffer.from(string)` (atau `Buffer.from(string, encoding)`). |
| 63 | +- Untuk semua kombinasi argumen lainnya (ini jauh lebih jarang), ganti juga `new Buffer(...arguments)` dengan `Buffer.from(...arguments)`. |
| 64 | + |
| 65 | +Perhatikan bahwa `Buffer.alloc()` juga _lebih cepat_ pada versi Node.js saat ini daripada `new Buffer(size).fill(0)`, yang seharusnya Anda perlukan untuk memastikan zero-filling. |
| 66 | + |
| 67 | +Mengaktifkan aturan ESLint [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) atau [node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) direkomendasikan untuk menghindari penggunaan `Buffer` API yang tidak aman secara tidak sengaja. |
| 68 | + |
| 69 | +Ada juga [JSCodeshift codemod](https://github.com/joyeecheung/node-dep-codemod#dep005) untuk memigrasikan konstruktor `Buffer` secara otomatis ke `Buffer.alloc()` atau `Buffer.from()`. Perhatikan bahwa saat ini hanya berfungsi dengan kasus di mana argumennya literal atau di mana konstruktor dipanggil dengan dua argumen. |
| 70 | + |
| 71 | +_Jika saat ini Anda mendukung versi Node.js yang lebih lama dan menghentikan dukungan untuk mereka tidak mungkin, atau jika Anda mendukung cabang paket Anda yang lebih lama, pertimbangkan untuk menggunakan [Varian 2](#varian-2) atau [Varian 3](#varian-3) di cabang lama, jadi orang yang menggunakan cabang lama itu juga akan menerima perbaikan. Dengan begitu, Anda akan menghilangkan potensi masalah yang disebabkan oleh penggunaan `Buffer` API yang tidak dijaga dan pengguna Anda tidak akan melihat peringatan penghentian runtime saat menjalankan kode Anda di Node.js 10._ |
| 72 | + |
| 73 | +## <!--variant-2-->Variant 2: Gunakan polyfill |
| 74 | + |
| 75 | +Ada tiga polyfill berbeda yang tersedia: |
| 76 | + |
| 77 | +- **[safer-buffer](https://www.npmjs.com/package/safer-buffer)** adalah pengganti drop-in untuk seluruh `Buffer` API, yang akan _dilempar_ saat menggunakan `new Buffer()`. |
| 78 | + |
| 79 | + Anda akan mengambil langkah yang sama persis seperti pada [Varian 1](#varian-1), tetapi dengan polyfill `const Buffer = require('safer-buffer').Buffer` di semua file tempat Anda menggunakan `Buffer` API baru. |
| 80 | + |
| 81 | + Jangan gunakan API `new Buffer()` yang lama. Dalam file apa pun di mana baris di atas ditambahkan, menggunakan `new Buffer()` API lama akan _throw_. |
| 82 | + |
| 83 | +- **[buffer-from](https://www.npmjs.com/package/buffer-from) dan/atau [buffer-alloc](https://www.npmjs.com/package/buffer-alloc)** adalah [ponyfills](https://ponyfill.com/) untuk masing-masing bagian dari `Buffer` API. Anda hanya perlu untuk menambahkan paket yang sesuai dengan API yang Anda gunakan. |
| 84 | + |
| 85 | + Anda akan mengimpor modul yang diperlukan dengan nama yang sesuai, mis. `const bufferFrom = require('buffer-from')` lalu gunakan itu sebagai ganti panggilan ke `Buffer baru()`, mis. `new Buffer('test')` menjadi `bufferFrom('test')`. |
| 86 | + |
| 87 | + Kelemahan dengan pendekatan ini adalah sedikit lebih banyak perubahan kode untuk dimigrasikan (seperti yang akan Anda lakukan menggunakan misalnya `Buffer.from()` dengan nama yang berbeda). |
| 88 | + |
| 89 | +- **[safe-buffer](https://www.npmjs.com/package/safe-buffer)** juga merupakan pengganti drop-in untuk seluruh `Buffer` API, tetapi menggunakan `new Buffer()` akan tetap berfungsi seperti sebelumnya. |
| 90 | + |
| 91 | + Kelemahan dari pendekatan ini adalah Anda juga dapat menggunakan `new Buffer()` API . yang lebih lama dalam kode Anda, yang bermasalah karena dapat menyebabkan masalah dalam kode Anda, dan akan mulai memancarkan peringatan penghentian runtime dimulai dengan Node.js 10 ([baca selengkapnya di sini](https://github.com/chalker/safer-buffer#why-not-safe-buffer)). |
| 92 | + |
| 93 | +Perhatikan bahwa dalam kedua kasus tersebut, Anda juga harus menghapus semua panggilan ke `Buffer` . yang lama API secara manual — hanya memasukkan `safe-buffer` tidak memperbaiki masalah dengan sendirinya, itu hanya menyediakan polyfill untuk API baru. Saya telah melihat orang-orang melakukan kesalahan itu. |
| 94 | + |
| 95 | +Mengaktifkan aturan ESLint [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) atau [node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) direkomendasikan. |
| 96 | + |
| 97 | +_Jangan lupa untuk menghentikan penggunaan polyfill setelah Anda menghentikan dukungan untuk Node.js <4.5.0._ |
| 98 | + |
| 99 | +## <!--variant-3-->Varian 3 — Deteksi manual, dengan pengaman |
| 100 | + |
| 101 | +Ini berguna jika Anda membuat instance `Buffer` hanya di beberapa tempat (mis. pembungkus di sekitar mereka. |
| 102 | + |
| 103 | +### `Buffer(0)` |
| 104 | + |
| 105 | +Kasus khusus untuk membuat buffer kosong ini dapat diganti dengan aman dengan `Buffer.concat([])`, yang mengembalikan hasil yang sama hingga ke Node.js 0.8.x. |
| 106 | + |
| 107 | +### `Buffer(bukanNumber)` |
| 108 | + |
| 109 | +Sebelum: |
| 110 | + |
| 111 | +```js |
| 112 | +const buf = new Buffer(notNumber, encoding); |
| 113 | +``` |
| 114 | + |
| 115 | +Sesudah: |
| 116 | + |
| 117 | +```js |
| 118 | +let buf; |
| 119 | +if (Buffer.from && Buffer.from !== Uint8Array.from) { |
| 120 | + buf = Buffer.from(notNumber, encoding); |
| 121 | +} else { |
| 122 | + if (typeof notNumber === 'number') { |
| 123 | + throw new Error('The "size" argument must be not of type number.'); |
| 124 | + } |
| 125 | + buf = new Buffer(notNumber, encoding); |
| 126 | +} |
| 127 | +``` |
| 128 | + |
| 129 | +`encoding` adalah opsional. |
| 130 | + |
| 131 | +Perhatikan bahwa `typeof notNumber` sebelum `new Buffer()` diperlukan (untuk kasus ketika argumen `notNumber` tidak hard-coded) dan _tidak disebabkan oleh penghentian konstruktor `Buffer`_ — justru _why_ the Konstruktor `Buffer` tidak digunakan lagi. Paket ekosistem yang tidak memiliki jenis pemeriksaan ini menyebabkan banyak masalah keamanan — situasi ketika input pengguna yang tidak bersih dapat berakhir di `Buffer(arg)` create masalah mulai dari DoS hingga membocorkan informasi sensitif ke penyerang dari memori proses. |
| 132 | + |
| 133 | +Ketika argumen `notNumber` di-hardcode (misalnya literal `"abc"` atau `[0,1,2]`), pemeriksaan `typeof` dapat dihilangkan. |
| 134 | + |
| 135 | +Juga, perhatikan bahwa menggunakan TypeScript tidak memperbaiki masalah ini untuk Anda — ketika libs ditulis dalam `TypeScript` digunakan dari JS, atau ketika input pengguna berakhir di sana — ia berperilaku persis seperti JS murni, seperti semua jenis pemeriksaan hanya waktu terjemahan dan tidak ada dalam kode JS aktual yang TS mengkompilasi ke. |
| 136 | + |
| 137 | +### `Buffer(number)` |
| 138 | + |
| 139 | +Untuk dukungan Node.js 0.10.x (dan di bawah): |
| 140 | + |
| 141 | +```js |
| 142 | +let buf; |
| 143 | +if (Buffer.alloc) { |
| 144 | + buf = Buffer.alloc(number); |
| 145 | +} else { |
| 146 | + buf = new Buffer(number); |
| 147 | + buf.fill(0); |
| 148 | +} |
| 149 | +``` |
| 150 | + |
| 151 | +Jika tidak (Node.js 0.12.x): |
| 152 | + |
| 153 | +```js |
| 154 | +const buf = Buffer.alloc ? Buffer.alloc(number) : new Buffer(number).fill(0); |
| 155 | +``` |
| 156 | + |
| 157 | +## Tentang `Buffer.allocUnsafe()` |
| 158 | + |
| 159 | +Berhati-hatilah saat menggunakan `Buffer.allocUnsafe()`: |
| 160 | + |
| 161 | +- Jangan gunakan jika Anda tidak memiliki alasan yang baik untuk |
| 162 | + - misalnya Anda mungkin tidak akan pernah melihat perbedaan kinerja untuk buffer kecil, pada kenyataannya, itu mungkin lebih cepat dengan `Buffer.alloc()`, |
| 163 | + - jika kode Anda tidak berada di jalur kode panas — Anda mungkin juga tidak akan melihat perbedaan, |
| 164 | + - perlu diingat bahwa pengisian nol meminimalkan potensi risiko. |
| 165 | +- Jika Anda menggunakannya, pastikan Anda tidak pernah mengembalikan buffer dalam keadaan terisi sebagian, |
| 166 | + - jika Anda menulisnya secara berurutan — selalu potong ke panjang tulisan yang sebenarnya |
| 167 | + |
| 168 | +Kesalahan dalam menangani buffer yang dialokasikan dengan `Buffer.allocUnsafe()` dapat mengakibatkan berbagai masalah, berkisar dari perilaku kode Anda yang tidak terdefinisi hingga data sensitif (input pengguna, kata sandi, sertifikat) bocor ke penyerang jarak jauh. |
| 169 | + |
| 170 | +_Perhatikan bahwa hal yang sama berlaku untuk penggunaan `new Buffer()` tanpa pengisian nol, tergantung pada Node.js versi (dan kurangnya pemeriksaan tipe juga menambahkan DoS ke daftar potensi masalah)._ |
| 171 | + |
| 172 | +## Pertanyaan Umum (FAQ) |
| 173 | + |
| 174 | +### <!--design-flaws-->Apa yang salah dengan konstruktor `Buffer`? |
| 175 | + |
| 176 | +Konstruktor `Buffer` dapat digunakan untuk membuat buffer dengan berbagai cara: |
| 177 | + |
| 178 | +- `New Buffer(42)` membuat `Buffer` sebesar 42 byte. Sebelum Node.js 8, buffer ini berisi *memori sewenang-wenang* untuk alasan kinerja, yang dapat mencakup apa saja mulai dari kode sumber program untuk kata sandi dan kunci enkripsi. |
| 179 | +- `new Buffer('abc')` membuat `Buffer` yang berisi versi UTF-8-encoded string '`'abc'`. Argumen kedua dapat menentukan pengkodean lain: misalnya,`new Buffer(string, 'base64')` dapat digunakan untuk mengonversi string Base64 menjadi yang asli urutan byte yang diwakilinya. |
| 180 | +- Ada beberapa kombinasi argumen lainnya. |
| 181 | + |
| 182 | +Ini berarti bahwa dalam kode seperti `var buffer = new Buffer(foo);`, *tidak mungkin untuk mengetahuinya apa sebenarnya isi buffer yang dihasilkan* tanpa mengetahui jenis `foo`. |
| 183 | + |
| 184 | +Terkadang, nilai `foo` berasal dari sumber eksternal. Misalnya, fungsi ini dapat diekspos sebagai layanan di server web, mengubah string UTF-8 menjadi bentuk Base64: |
| 185 | + |
| 186 | +```js |
| 187 | +function stringToBase64(req, res) { |
| 188 | + // The request body should have the format of `{ string: 'foobar' }`. |
| 189 | + const rawBytes = new Buffer(req.body.string); |
| 190 | + const encoded = rawBytes.toString('base64'); |
| 191 | + res.end({ encoded }); |
| 192 | +} |
| 193 | +``` |
| 194 | + |
| 195 | +Perhatikan bahwa kode ini _tidak_ memvalidasi jenis `req.body.string`: |
| 196 | + |
| 197 | +- `req.body.string` diharapkan berupa string. Jika ini masalahnya, semuanya berjalan dengan baik. |
| 198 | +- `req.body.string` dikendalikan oleh klien yang mengirimkan permintaan. |
| 199 | +- Jika `req.body.string` adalah *number* `50`, `rawBytes` akan menjadi `50` byte: |
| 200 | + - Sebelum Node.js 8, konten tidak akan diinisialisasi |
| 201 | + - Setelah Node.js 8, konten akan menjadi `50` byte dengan nilai `0` |
| 202 | + |
| 203 | +Karena pemeriksaan tipe yang hilang, penyerang dapat dengan sengaja mengirim nomor sebagai bagian dari permintaan. Dengan menggunakan ini, mereka dapat: |
| 204 | + |
| 205 | +- Baca memori yang tidak diinisialisasi. Ini **akan** membocorkan kata sandi, kunci enkripsi, dan lainnya jenis informasi sensitif. (Kebocoran informasi) |
| 206 | +- Memaksa program untuk mengalokasikan sejumlah besar memori. Misalnya, saat menentukan `500000000` sebagai nilai input, setiap permintaan akan mengalokasikan 500MB memori. Ini dapat digunakan untuk menghabiskan memori yang tersedia dari suatu program sepenuhnya dan membuatnya crash, atau memperlambatnya secara signifikan. (Kegagalan layanan) |
| 207 | + |
| 208 | +Kedua skenario ini dianggap sebagai masalah keamanan yang serius di dunia nyata konteks server web. |
| 209 | + |
| 210 | +Saat menggunakan `Buffer.from(req.body.string)` sebagai gantinya, melewatkan nomor akan selalu melempar pengecualian sebagai gantinya, memberikan perilaku terkontrol yang selalu bisa ditangani oleh program. |
| 211 | + |
| 212 | +### <!--ecosystem-usage-->Konstruktor `Buffer()` telah ditinggalkan untuk sementara waktu. Apakah ini benar-benar masalah? |
| 213 | + |
| 214 | +Survei kode di ekosistem `npm` telah menunjukkan bahwa konstruktor `Buffer()` masih banyak digunakan. Ini termasuk kode baru, dan penggunaan keseluruhan kode tersebut sebenarnya telah *increasing*. |
0 commit comments