Skip to content

Commit 3c02727

Browse files
committed
buffer: backport --zero-fill-buffers command line option
This backports the --zero-fill-buffers command line flag introduced in master. When used, all Buffer and SlowBuffer instances will zero fill by default. This does *not* backport any of the other Buffer API or behavior changes. PR-URL: #5744 Reviewed-By: Сковорода Никита Андреевич <[email protected]> Reviewed-By: Trevor Norris <[email protected]>
1 parent 90c2063 commit 3c02727

File tree

7 files changed

+73
-3
lines changed

7 files changed

+73
-3
lines changed

doc/api/buffer.markdown

+17
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,23 @@ for (var b of buf)
145145
Additionally, the [`buf.values()`][], [`buf.keys()`][], and
146146
[`buf.entries()`][] methods can be used to create iterators.
147147

148+
## The `--zero-fill-buffers` command line option
149+
150+
Node.js can be started using the `--zero-fill-buffers` command line option to
151+
force all newly allocated `Buffer` and `SlowBuffer` instances created using
152+
either `new Buffer(size)` and `new SlowBuffer(size)` to be *automatically
153+
zero-filled* upon creation. Use of this flag *changes the default behavior* of
154+
these methods and *can have a significant impact* on performance. Use of the
155+
`--zero-fill-buffers` option is recommended only when absolutely necessary to
156+
enforce that newly allocated `Buffer` instances cannot contain potentially
157+
sensitive data.
158+
159+
```
160+
$ node --zero-fill-buffers
161+
> Buffer(5);
162+
<Buffer 00 00 00 00 00>
163+
```
164+
148165
## Class: Buffer
149166

150167
The Buffer class is a global type for dealing with binary data directly.

doc/api/cli.markdown

+3
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ instances.
9393

9494
Track heap object allocations for heap snapshots.
9595

96+
### `--zero-fill-buffers`
97+
98+
Automatically zero-fills all newly allocated Buffer and SlowBuffer instances.
9699

97100
### `--prof-process`
98101

doc/node.1

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ of the event loop.
8787
.BR \-\-track\-heap-objects
8888
Track heap object allocations for heap snapshots.
8989

90+
.TP
91+
.BR \-\-zero\-fill\-buffers
92+
Automatically zero-fills all newly allocated Buffer and SlowBuffer instances.
93+
9094
.TP
9195
.BR \-\-prof\-process
9296
Process v8 profiler output generated using the v8 option \fB\-\-prof\fR

src/node.cc

+7-1
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,9 @@ Local<Value> WinapiErrnoException(Isolate* isolate,
946946

947947

948948
void* ArrayBufferAllocator::Allocate(size_t size) {
949-
if (env_ == nullptr || !env_->array_buffer_allocator_info()->no_zero_fill())
949+
if (env_ == nullptr ||
950+
!env_->array_buffer_allocator_info()->no_zero_fill() ||
951+
zero_fill_all_buffers)
950952
return calloc(size, 1);
951953
env_->array_buffer_allocator_info()->reset_fill_flag();
952954
return malloc(size);
@@ -3261,6 +3263,8 @@ static void PrintHelp() {
32613263
"snapshots\n"
32623264
" --prof-process process v8 profiler output generated\n"
32633265
" using --prof\n"
3266+
" --zero-fill-buffers automatically zero-fill all newly allocated\n"
3267+
" Buffer and SlowBuffer instances\n"
32643268
" --v8-options print v8 command line options\n"
32653269
#if HAVE_OPENSSL
32663270
" --tls-cipher-list=val use an alternative default TLS cipher list\n"
@@ -3400,6 +3404,8 @@ static void ParseArgs(int* argc,
34003404
} else if (strcmp(arg, "--prof-process") == 0) {
34013405
prof_process = true;
34023406
short_circuit = true;
3407+
} else if (strcmp(arg, "--zero-fill-buffers") == 0) {
3408+
zero_fill_all_buffers = true;
34033409
} else if (strcmp(arg, "--v8-options") == 0) {
34043410
new_v8_argv[new_v8_argc] = "--help";
34053411
new_v8_argc += 1;

src/node_buffer.cc

+9-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,14 @@
4848
CHECK_NOT_OOB(end <= end_max); \
4949
size_t length = end - start;
5050

51+
#define BUFFER_MALLOC(length) \
52+
zero_fill_all_buffers ? calloc(length, 1) : malloc(length)
53+
5154
namespace node {
55+
56+
// if true, all Buffer and SlowBuffer instances will automatically zero-fill
57+
bool zero_fill_all_buffers = false;
58+
5259
namespace Buffer {
5360

5461
using v8::ArrayBuffer;
@@ -220,7 +227,7 @@ MaybeLocal<Object> New(Isolate* isolate,
220227
// nullptr for zero-sized allocation requests. Normalize by always using
221228
// a nullptr.
222229
if (length > 0) {
223-
data = static_cast<char*>(malloc(length));
230+
data = static_cast<char*>(BUFFER_MALLOC(length));
224231

225232
if (data == nullptr)
226233
return Local<Object>();
@@ -266,7 +273,7 @@ MaybeLocal<Object> New(Environment* env, size_t length) {
266273

267274
void* data;
268275
if (length > 0) {
269-
data = malloc(length);
276+
data = BUFFER_MALLOC(length);
270277
if (data == nullptr)
271278
return Local<Object>();
272279
} else {

src/node_buffer.h

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
#include "v8.h"
66

77
namespace node {
8+
9+
extern bool zero_fill_all_buffers;
10+
811
namespace Buffer {
912

1013
static const unsigned int kMaxLength =
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use strict';
2+
// Flags: --zero-fill-buffers
3+
4+
// when using --zero-fill-buffers, every Buffer and SlowBuffer
5+
// instance must be zero filled upon creation
6+
7+
require('../common');
8+
const SlowBuffer = require('buffer').SlowBuffer;
9+
const assert = require('assert');
10+
11+
function isZeroFilled(buf) {
12+
for (let n = 0; n < buf.length; n++)
13+
if (buf[n] > 0) return false;
14+
return true;
15+
}
16+
17+
// This can be somewhat unreliable because the
18+
// allocated memory might just already happen to
19+
// contain all zeroes. The test is run multiple
20+
// times to improve the reliability.
21+
for (let i = 0; i < 50; i++) {
22+
const bufs = [
23+
SlowBuffer(20),
24+
Buffer(20),
25+
new SlowBuffer(20)
26+
];
27+
for (const buf of bufs) {
28+
assert(isZeroFilled(buf));
29+
}
30+
}

0 commit comments

Comments
 (0)