Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

buffer: backport --zero-fill-buffers command line option #5751

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions doc/api/buffer.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,23 @@ While more efficient, it introduces subtle incompatibilities with the typed
arrays specification. `ArrayBuffer#slice()` makes a copy of the slice while
`Buffer#slice()` creates a view.

## The `--zero-fill-buffers` command line option

Node.js can be started using the `--zero-fill-buffers` command line option to
force all newly allocated `Buffer` and `SlowBuffer` instances created using
either `new Buffer(size)` and `new SlowBuffer(size)` to be *automatically
zero-filled* upon creation. Use of this flag *changes the default behavior* of
these methods and *can have a significant impact* on performance. Use of the
`--zero-fill-buffers` option is recommended only when absolutely necessary to
enforce that newly allocated `Buffer` instances cannot contain potentially
sensitive data.

```
$ node --zero-fill-buffers
> Buffer(5);
<Buffer 00 00 00 00 00>
```

## Class: Buffer

The Buffer class is a global type for dealing with binary data directly.
Expand Down
3 changes: 3 additions & 0 deletions doc/node.1
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ and servers.

--throw-deprecation throw errors on deprecations

--zero-fill-buffers Automatically zero-fills all newly allocated Buffer
and SlowBuffer instances.

--v8-options print v8 command line options

--max-stack-size=val set max v8 stack size (bytes)
Expand Down
5 changes: 5 additions & 0 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2635,6 +2635,8 @@ static void PrintHelp() {
" --no-deprecation silence deprecation warnings\n"
" --trace-deprecation show stack traces on deprecations\n"
" --v8-options print v8 command line options\n"
" --zero-fill-buffers automatically zero-fill all newly allocated\n"
" Buffer and SlowBuffer instances\n"
" --max-stack-size=val set max v8 stack size (bytes)\n"
#if HAVE_OPENSSL
" --enable-ssl3 enable ssl3\n"
Expand Down Expand Up @@ -2719,6 +2721,9 @@ static void ParseArgs(int argc, char **argv) {
argv[i] = const_cast<char*>("");
} else if (strcmp(arg, "--v8-options") == 0) {
argv[i] = const_cast<char*>("--help");
} else if (strcmp(arg, "--zero-fill-buffers") == 0) {
argv[i] = const_cast<char*>("");
zero_fill_all_buffers = true;
} else if (strcmp(arg, "--no-deprecation") == 0) {
argv[i] = const_cast<char*>("");
no_deprecation = true;
Expand Down
11 changes: 10 additions & 1 deletion src/node_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,22 @@
#include <assert.h>
#include <string.h> // memcpy
#include <limits.h>
#include <stdio.h>

#define MIN(a,b) ((a) < (b) ? (a) : (b))

#define BUFFER_CLASS_ID (0xBABE)

#define BUFFER_MALLOC(length) \
zero_fill_all_buffers ? \
static_cast<char*>(calloc(length, 1)) : \
new char[length]

namespace node {

// if true, all Buffer and SlowBuffer instances will automatically zero-fill
bool zero_fill_all_buffers = false;

using namespace v8;

#define SLICE_ARGS(start_arg, end_arg) \
Expand Down Expand Up @@ -178,7 +187,7 @@ void Buffer::Replace(char *data, size_t length,
if (callback_) {
data_ = data;
} else if (length_) {
data_ = new char[length_];
data_ = BUFFER_MALLOC(length_);
if (data)
memcpy(data_, data, length_);
V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer) + length_);
Expand Down
1 change: 1 addition & 0 deletions src/node_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ namespace node {

*/

extern bool zero_fill_all_buffers;

class NODE_EXTERN Buffer: public ObjectWrap {
public:
Expand Down
29 changes: 29 additions & 0 deletions test/simple/test-buffer-zero-fill-cli.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Flags: --zero-fill-buffers

// when using --zero-fill-buffers, every Buffer and SlowBuffer
// instance must be zero filled upon creation

require('../common');
var SlowBuffer = require('buffer').SlowBuffer;
var assert = require('assert');

function isZeroFilled(buf) {
for (var n = 0; n < buf.length; n++)
if (buf[n] > 0) return false;
return true;
}

// This can be somewhat unreliable because the
// allocated memory might just already happen to
// contain all zeroes. The test is run multiple
// times to improve the reliability.
for (var i = 0; i < 50; i++) {
var bufs = [
SlowBuffer(20),
Buffer(20),
new SlowBuffer(20)
];
bufs.forEach(function(buf) {
assert(isZeroFilled(buf));
});
}