Skip to content

Commit e5d71cd

Browse files
committed
buffer: add Buffer.harden() method
1 parent f70261f commit e5d71cd

1 file changed

Lines changed: 37 additions & 2 deletions

File tree

lib/buffer.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const {
6363

6464
const {
6565
codes: {
66+
ERR_ASSERTION,
6667
ERR_BUFFER_OUT_OF_BOUNDS,
6768
ERR_INVALID_ARG_TYPE,
6869
ERR_INVALID_ARG_VALUE,
@@ -109,8 +110,13 @@ let poolSize, poolOffset, allocPool;
109110
// do not own the ArrayBuffer allocator. Zero fill is always on in that case.
110111
const zeroFill = bindingZeroFill || [0];
111112

113+
// Hardening Buffer enables Buffer constructor runtime deprecation,
114+
// disables pooling, and enables mandratory zero-fill. This is more secure, but
115+
// has potential performance impact, depending on the usecase.
116+
let hardened = false;
117+
112118
function createUnsafeBuffer(size) {
113-
zeroFill[0] = 0;
119+
zeroFill[0] = hardened ? 1 : 0;
114120
try {
115121
return new FastBuffer(size);
116122
} finally {
@@ -140,6 +146,15 @@ const bufferWarning = 'Buffer() is deprecated due to security and usability ' +
140146
'Buffer.allocUnsafe(), or Buffer.from() methods instead.';
141147

142148
function showFlaggedDeprecation() {
149+
if (hardened) {
150+
if (bufferWarningAlreadyEmitted) return;
151+
process.emitWarning(
152+
bufferWarning + ' Buffer() will soon throw in hardened mode.',
153+
'DeprecationWarning', 'DEP0XXX');
154+
bufferWarningAlreadyEmitted = true;
155+
return;
156+
}
157+
143158
if (bufferWarningAlreadyEmitted ||
144159
++nodeModulesCheckCounter > 10000 ||
145160
(!require('internal/options').getOptionValue('--pending-deprecation') &&
@@ -157,6 +172,26 @@ function showFlaggedDeprecation() {
157172
bufferWarningAlreadyEmitted = true;
158173
}
159174

175+
// Calling this method does not affect existing buffers, only new ones.
176+
Buffer.harden = function() {
177+
if (hardened) return;
178+
if (isInsideNodeModules()) {
179+
throw new ERR_ASSERTION(
180+
'Buffer.harden() should be called only from the top-level module. ' +
181+
'Calling Buffer.harden() from dependencies is not supported.'
182+
);
183+
}
184+
hardened = true;
185+
Object.defineProperty(Buffer, 'poolSize', {
186+
enumerable: true,
187+
get: () => 0,
188+
set: () => {},
189+
});
190+
Object.freeze(Buffer);
191+
Object.freeze(Buffer.prototype);
192+
Object.freeze(module.exports);
193+
};
194+
160195
function toInteger(n, defaultVal) {
161196
n = +n;
162197
if (!Number.isNaN(n) &&
@@ -365,7 +400,7 @@ function allocate(size) {
365400
if (size <= 0) {
366401
return new FastBuffer();
367402
}
368-
if (size < (Buffer.poolSize >>> 1)) {
403+
if (size < (Buffer.poolSize >>> 1) && !hardened) {
369404
if (size > (poolSize - poolOffset))
370405
createPool();
371406
const b = new FastBuffer(allocPool, poolOffset, size);

0 commit comments

Comments
 (0)