Browse Source

buffer: reject negative SlowBuffer offsets

Reject negative offsets in SlowBuffer::MakeFastBuffer(), it allows
the creation of buffers that point to arbitrary addresses.

Reported by Trevor Norris.
v0.8.18-release
Ben Noordhuis 12 years ago
parent
commit
498200b87c
  1. 2
      lib/buffer.js
  2. 13
      src/node_buffer.cc
  3. 45
      test/simple/test-buffer.js

2
lib/buffer.js

@ -557,7 +557,7 @@ Buffer.prototype.slice = function(start, end) {
if (end === undefined) end = this.length; if (end === undefined) end = this.length;
if (end > this.length) throw new Error('oob'); if (end > this.length) throw new Error('oob');
if (start > end) throw new Error('oob'); if (start > end) throw new Error('oob');
if (start < 0) throw new Error('start out of bounds');
return new Buffer(this.parent, end - start, +start + this.offset); return new Buffer(this.parent, end - start, +start + this.offset);
}; };

13
src/node_buffer.cc

@ -708,6 +708,19 @@ Handle<Value> Buffer::MakeFastBuffer(const Arguments &args) {
uint32_t offset = args[2]->Uint32Value(); uint32_t offset = args[2]->Uint32Value();
uint32_t length = args[3]->Uint32Value(); uint32_t length = args[3]->Uint32Value();
if (offset > buffer->length_) {
return ThrowRangeError("offset out of range");
}
if (offset + length > buffer->length_) {
return ThrowRangeError("length out of range");
}
// Check for wraparound. Safe because offset and length are unsigned.
if (offset + length < offset) {
return ThrowRangeError("offset or length out of range");
}
fast_buffer->SetIndexedPropertiesToExternalArrayData(buffer->data_ + offset, fast_buffer->SetIndexedPropertiesToExternalArrayData(buffer->data_ + offset,
kExternalUnsignedByteArray, kExternalUnsignedByteArray,
length); length);

45
test/simple/test-buffer.js

@ -22,6 +22,7 @@
var common = require('../common'); var common = require('../common');
var assert = require('assert'); var assert = require('assert');
var SlowBuffer = require('buffer').SlowBuffer;
var Buffer = require('buffer').Buffer; var Buffer = require('buffer').Buffer;
var b = Buffer(1024); // safe constructor var b = Buffer(1024); // safe constructor
@ -745,3 +746,47 @@ assert.throws(function() {
assert.throws(function() { assert.throws(function() {
new Buffer(0xFFFFFFFFF); new Buffer(0xFFFFFFFFF);
}, TypeError); }, TypeError);
// SlowBuffer sanity checks.
assert.throws(function() {
var len = 0xfffff;
var sbuf = new SlowBuffer(len);
var buf = new Buffer(sbuf, len, 0);
SlowBuffer.makeFastBuffer(sbuf, buf, -len, len); // Should throw.
for (var i = 0; i < len; ++i) buf[i] = 0x42; // Try to force segfault.
}, RangeError);
assert.throws(function() {
var len = 0xfffff;
var sbuf = new SlowBuffer(len);
var buf = new Buffer(sbuf, len, -len); // Should throw.
for (var i = 0; i < len; ++i) buf[i] = 0x42; // Try to force segfault.
}, RangeError);
assert.throws(function() {
var len = 0xfffff;
var sbuf = new SlowBuffer(len);
sbuf = sbuf.slice(-len); // Should throw.
for (var i = 0; i < len; ++i) sbuf[i] = 0x42; // Try to force segfault.
}, RangeError);
assert.throws(function() {
var sbuf = new SlowBuffer(1);
var buf = new Buffer(sbuf, 1, 0);
buf.length = 0xffffffff;
buf.slice(0xffffff0, 0xffffffe); // Should throw.
}, Error);
assert.throws(function() {
var sbuf = new SlowBuffer(8);
var buf = new Buffer(sbuf, 8, 0);
buf.slice(-8); // Should throw. Throws Error instead of RangeError
// for the sake of v0.8 compatibility.
}, Error);
assert.throws(function() {
var sbuf = new SlowBuffer(16);
var buf = new Buffer(sbuf, 8, 8);
buf.slice(-8); // Should throw. Throws Error instead of RangeError
// for the sake of v0.8 compatibility.
}, Error);

Loading…
Cancel
Save