Skip to content

Commit d5bdda7

Browse files
committed
fast buffer bounds checking in copy()
1 parent 6ea9972 commit d5bdda7

3 files changed

Lines changed: 48 additions & 16 deletions

File tree

lib/buffer.js

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,29 @@ SlowBuffer.prototype.inspect = function () {
1717
};
1818

1919

20-
SlowBuffer.prototype.toString = function (encoding, start, stop) {
20+
SlowBuffer.prototype.toString = function (encoding, start, end) {
2121
encoding = String(encoding || 'utf8').toLowerCase();
2222
start = +start || 0;
23-
if (typeof stop == "undefined") stop = this.length;
23+
if (typeof end == "undefined") end = this.length;
2424

2525
// Fastpath empty strings
26-
if (+stop == start) {
26+
if (+end == start) {
2727
return '';
2828
}
2929

3030
switch (encoding) {
3131
case 'utf8':
3232
case 'utf-8':
33-
return this.utf8Slice(start, stop);
33+
return this.utf8Slice(start, end);
3434

3535
case 'ascii':
36-
return this.asciiSlice(start, stop);
36+
return this.asciiSlice(start, end);
3737

3838
case 'binary':
39-
return this.binarySlice(start, stop);
39+
return this.binarySlice(start, end);
4040

4141
case 'base64':
42-
return this.base64Slice(start, stop);
42+
return this.base64Slice(start, end);
4343

4444
default:
4545
throw new Error('Unknown encoding');
@@ -212,14 +212,19 @@ Buffer.prototype.write = function write (string, offset, encoding) {
212212

213213

214214
// toString(encoding, start=0, end=buffer.length)
215-
Buffer.prototype.toString = function toString (encoding, start, end) {
216-
encoding || (encoding = 'utf8');
217-
start || (start = 0);
218-
end || (end = this.length);
215+
Buffer.prototype.toString = function (encoding, start, end) {
216+
if (typeof encoding == 'undefined') encoding = 'utf8';
219217

220-
// Make sure we aren't oob
221-
if (end > this.length) {
218+
if (typeof start == 'undefined' || start < 0) {
219+
start = 0;
220+
} else if (start > this.length) {
221+
start = this.length;
222+
}
223+
224+
if (typeof end == "undefined" || end > this.length) {
222225
end = this.length;
226+
} else if (end < 0) {
227+
end = 0;
223228
}
224229

225230
return this.parent.toString(encoding, start + this.offset, end + this.offset);
@@ -232,14 +237,37 @@ Buffer.byteLength = SlowBuffer.byteLength;
232237

233238
// copy(targetBuffer, targetStart, sourceStart, sourceEnd=buffer.length)
234239
Buffer.prototype.copy = function copy (target, target_start, start, end) {
240+
var source = this;
235241
start || (start = 0);
236242
end || (end = this.length);
237243

244+
if (end < start) throw new Error("sourceEnd < sourceStart");
245+
246+
// Copy 0 bytes; we're done
247+
if (end === start) return 0;
248+
if (target.length == 0 || source.length == 0) return 0;
249+
250+
if (target_start < 0 || target_start >= target.length) {
251+
throw new Error("targetStart out of bounds");
252+
}
253+
254+
if (start < 0 || start >= source.length) {
255+
throw new Error("sourceStart out of bounds");
256+
}
257+
258+
if (end < 0 || end > source.length) {
259+
throw new Error("sourceEnd out of bounds");
260+
}
261+
238262
// Are we oob?
239263
if (end > this.length) {
240264
end = this.length;
241265
}
242266

267+
if (target.length - target_start < end - start) {
268+
end = target.length - target_start + start;
269+
}
270+
243271
return this.parent.copy(target.parent,
244272
target_start + target.offset,
245273
start + this.offset,

src/node_buffer.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,10 @@ Handle<Value> Buffer::Copy(const Arguments &args) {
485485
"sourceEnd out of bounds")));
486486
}
487487

488-
ssize_t to_copy = MIN(source_end - source_start,
489-
target->length() - target_start);
488+
ssize_t to_copy = MIN(MIN(source_end - source_start,
489+
target->length() - target_start),
490+
source->length() - source_start);
491+
490492

491493
if (target->blob_ == source->blob_) {
492494
// need to use slightly slower memmove is the ranges might overlap

test/simple/test-buffer.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ for (var i = 0; i < 1024; i++) {
1919
}
2020

2121
var c = new Buffer(512);
22+
console.log("c.length == %d", c.length);
23+
assert.strictEqual(512, c.length);
2224

2325
// copy 512 bytes, from 0 to 512.
2426
var copied = b.copy(c, 0, 0, 512);
2527
console.log("copied " + copied + " bytes from b into c");
26-
assert.strictEqual(512, copied);
28+
assert.equal(512, copied);
2729
for (var i = 0; i < c.length; i++) {
2830
common.print('.');
2931
assert.equal(i % 256, c[i]);

0 commit comments

Comments
 (0)