Skip to content

Commit fb03e57

Browse files
jasnellMyles Borins
authored andcommitted
buffer: backport --zero-fill-buffers cli 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: #5745 Reviewed-By: Trevor Norris <[email protected]>
1 parent 55f8689 commit fb03e57

File tree

6 files changed

+70
-3
lines changed

6 files changed

+70
-3
lines changed

‎doc/api/buffer.markdown‎

Lines changed: 17 additions & 0 deletions
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/node.1‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ Process v8 profiler output generated using the v8 option \fB\-\-prof\fR
9595
.BR\-\-v8\-options
9696
Print v8 command line options.
9797

98+
.TP
99+
.BR\-\-zero\-fill\-buffers
100+
Automatically zero-fills all newly allocated Buffer and SlowBuffer instances.
101+
98102
.TP
99103
.BR\-\-tls\-cipher\-list =\fIlist\fR
100104
Specify an alternative default TLS cipher list. (Requires Node.js to be built with crypto support. (Default))

‎src/node.cc‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,9 @@ Local<Value> WinapiErrnoException(Isolate* isolate,
947947

948948

949949
void* ArrayBufferAllocator::Allocate(size_t size){
950-
if (env_ == nullptr || !env_->array_buffer_allocator_info()->no_zero_fill())
950+
if (env_ == nullptr ||
951+
!env_->array_buffer_allocator_info()->no_zero_fill() ||
952+
zero_fill_all_buffers)
951953
returncalloc(size, 1);
952954
env_->array_buffer_allocator_info()->reset_fill_flag();
953955
returnmalloc(size);
@@ -3283,6 +3285,8 @@ static void PrintHelp(){
32833285
"snapshots\n"
32843286
" --prof-process process v8 profiler output generated\n"
32853287
" using --prof\n"
3288+
" --zero-fill-buffers automatically zero-fill all newly allocated\n"
3289+
" Buffer and SlowBuffer instances\n"
32863290
" --v8-options print v8 command line options\n"
32873291
#if HAVE_OPENSSL
32883292
" --tls-cipher-list=val use an alternative default TLS cipher list\n"
@@ -3422,6 +3426,8 @@ static void ParseArgs(int* argc,
34223426
} elseif (strcmp(arg, "--prof-process") == 0){
34233427
prof_process = true;
34243428
short_circuit = true;
3429+
} elseif (strcmp(arg, "--zero-fill-buffers") == 0){
3430+
zero_fill_all_buffers = true;
34253431
} elseif (strcmp(arg, "--v8-options") == 0){
34263432
new_v8_argv[new_v8_argc] = "--help";
34273433
new_v8_argc += 1;

‎src/node_buffer.cc‎

Lines changed: 9 additions & 2 deletions
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+
#defineBUFFER_MALLOC(length) \
52+
zero_fill_all_buffers ? calloc(length, 1) : malloc(length)
53+
5154
namespacenode{
55+
56+
// if true, all Buffer and SlowBuffer instances will automatically zero-fill
57+
bool zero_fill_all_buffers = false;
58+
5259
namespaceBuffer{
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‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
#include"v8.h"
66

77
namespacenode{
8+
9+
externbool zero_fill_all_buffers;
10+
811
namespaceBuffer{
912

1013
staticconstunsignedintkMaxLength =
Lines changed: 30 additions & 0 deletions
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+
constSlowBuffer=require('buffer').SlowBuffer;
9+
constassert=require('assert');
10+
11+
functionisZeroFilled(buf){
12+
for(letn=0;n<buf.length;n++)
13+
if(buf[n]>0)returnfalse;
14+
returntrue;
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(leti=0;i<50;i++){
22+
constbufs=[
23+
SlowBuffer(20),
24+
Buffer(20),
25+
newSlowBuffer(20)
26+
];
27+
for(constbufofbufs){
28+
assert(isZeroFilled(buf));
29+
}
30+
}

0 commit comments

Comments
(0)