buffer: slice on zero length buffer

SlowBuffer(0) passes NULL instead of doing malloc(0). So when someone
attempted to SlowBuffer(0).slice(0, 1) an assert would fail in
smalloc::SliceOnto.

It's important that the check go where it is because the resulting
Buffer needs to have external array data allocated. In the case a user
tries to slice a zero length Buffer it will also have NULL passed as the
data argument.

Also fixed where the .parent attribute was set for zero length Buffers.
There is no need to track the source of slice if the slice isn't
actually occurring.
pull/5010/head
Trevor Norris 2013-07-22 17:04:17 -07:00
parent 0f8de5e1f9
commit 35e0d60d0c
3 changed files with 18 additions and 7 deletions

View File

@ -83,10 +83,12 @@ function Buffer(subject, encoding) {
if (this.length < Buffer.poolSize / 2 && this.length > 0) {
if (this.length > poolSize - poolOffset)
createPool();
this.parent = sliceOnto(allocPool,
this,
poolOffset,
poolOffset + this.length);
var parent = sliceOnto(allocPool,
this,
poolOffset,
poolOffset + this.length);
if (this.length > 0)
this.parent = parent;
poolOffset += this.length;
} else {
alloc(this, this.length);
@ -373,8 +375,9 @@ Buffer.prototype.slice = function(start, end) {
var buf = new Buffer();
sliceOnto(this, buf, start, end);
buf.parent = this.parent === undefined ? this : this.parent;
buf.length = end - start;
if (buf.length > 0)
buf.parent = this.parent === undefined ? this : this.parent;
return buf;
};

View File

@ -124,15 +124,16 @@ void SliceOnto(const FunctionCallbackInfo<Value>& args) {
size_t source_len = source->GetIndexedPropertiesExternalArrayDataLength();
size_t start = args[2]->Uint32Value();
size_t end = args[3]->Uint32Value();
size_t length = end - start;
assert(!dest->HasIndexedPropertiesInExternalArrayData());
assert(source_data != NULL);
assert(source_data != NULL || length == 0);
assert(end <= source_len);
assert(start <= end);
dest->SetIndexedPropertiesToExternalArrayData(source_data + start,
kExternalUnsignedByteArray,
end - start);
length);
args.GetReturnValue().Set(source);
}

View File

@ -947,6 +947,13 @@ assert.throws(function() { buf.readInt8(0); }, RangeError);
assert.equal(buf.slice(-i), s.slice(-i));
assert.equal(buf.slice(0, -i), s.slice(0, -i));
}
// try to slice a zero length Buffer
// see https://github.com/joyent/node/issues/5881
SlowBuffer(0).slice(0, 1);
// make sure a zero length slice doesn't set the .parent attribute
assert.equal(Buffer(5).slice(0,0).parent, undefined);
// and make sure a proper slice does have a parent
assert.ok(typeof Buffer(5).slice(0, 5).parent === 'object');
})();
// Make sure byteLength properly checks for base64 padding