Skip to content

Commit

Permalink
Fix overflow issues on writing/reading integers
Browse files Browse the repository at this point in the history
  • Loading branch information
tonistiigi committed Feb 27, 2013
1 parent df655de commit 0504f9f
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 25 deletions.
62 changes: 37 additions & 25 deletions index.js
Expand Up @@ -689,6 +689,8 @@ Buffer.prototype.readUInt8 = function(offset, noAssert) {
'Trying to read beyond buffer length');
}

if (offset >= buffer.length) return;

return buffer.parent[buffer.offset + offset];
};

Expand All @@ -707,12 +709,18 @@ function readUInt16(buffer, offset, isBigEndian, noAssert) {
'Trying to read beyond buffer length');
}

if (offset >= buffer.length) return 0;

if (isBigEndian) {
val = buffer.parent[buffer.offset + offset] << 8;
val |= buffer.parent[buffer.offset + offset + 1];
if (offset + 1 < buffer.length) {
val |= buffer.parent[buffer.offset + offset + 1];
}
} else {
val = buffer.parent[buffer.offset + offset];
val |= buffer.parent[buffer.offset + offset + 1] << 8;
if (offset + 1 < buffer.length) {
val |= buffer.parent[buffer.offset + offset + 1] << 8;
}
}

return val;
Expand Down Expand Up @@ -740,16 +748,24 @@ function readUInt32(buffer, offset, isBigEndian, noAssert) {
'Trying to read beyond buffer length');
}

if (offset >= buffer.length) return 0;

if (isBigEndian) {
val = buffer.parent[buffer.offset + offset + 1] << 16;
val |= buffer.parent[buffer.offset + offset + 2] << 8;
val |= buffer.parent[buffer.offset + offset + 3];
if (offset + 1 < buffer.length)
val = buffer.parent[buffer.offset + offset + 1] << 16;
if (offset + 2 < buffer.length)
val |= buffer.parent[buffer.offset + offset + 2] << 8;
if (offset + 3 < buffer.length)
val |= buffer.parent[buffer.offset + offset + 3];
val = val + (buffer.parent[buffer.offset + offset] << 24 >>> 0);
} else {
val = buffer.parent[buffer.offset + offset + 2] << 16;
val |= buffer.parent[buffer.offset + offset + 1] << 8;
if (offset + 2 < buffer.length)
val = buffer.parent[buffer.offset + offset + 2] << 16;
if (offset + 1 < buffer.length)
val |= buffer.parent[buffer.offset + offset + 1] << 8;
val |= buffer.parent[buffer.offset + offset];
val = val + (buffer.parent[buffer.offset + offset + 3] << 24 >>> 0);
if (offset + 3 < buffer.length)
val = val + (buffer.parent[buffer.offset + offset + 3] << 24 >>> 0);
}

return val;
Expand Down Expand Up @@ -821,6 +837,8 @@ Buffer.prototype.readInt8 = function(offset, noAssert) {
'Trying to read beyond buffer length');
}

if (offset >= buffer.length) return;

neg = buffer.parent[buffer.offset + offset] & 0x80;
if (!neg) {
return (buffer.parent[buffer.offset + offset]);
Expand Down Expand Up @@ -971,7 +989,9 @@ Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
verifuint(value, 0xff);
}

buffer.parent[buffer.offset + offset] = value;
if (offset < buffer.length) {
buffer.parent[buffer.offset + offset] = value;
}
};

function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
Expand All @@ -991,13 +1011,12 @@ function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
verifuint(value, 0xffff);
}

if (isBigEndian) {
buffer.parent[buffer.offset + offset] = (value & 0xff00) >>> 8;
buffer.parent[buffer.offset + offset + 1] = value & 0x00ff;
} else {
buffer.parent[buffer.offset + offset + 1] = (value & 0xff00) >>> 8;
buffer.parent[buffer.offset + offset] = value & 0x00ff;
for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) {
buffer.parent[buffer.offset + offset + i] =
(value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>>
(isBigEndian ? 1 - i : i) * 8;
}

}

Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
Expand Down Expand Up @@ -1025,16 +1044,9 @@ function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
verifuint(value, 0xffffffff);
}

if (isBigEndian) {
buffer.parent[buffer.offset + offset] = (value >>> 24) & 0xff;
buffer.parent[buffer.offset + offset + 1] = (value >>> 16) & 0xff;
buffer.parent[buffer.offset + offset + 2] = (value >>> 8) & 0xff;
buffer.parent[buffer.offset + offset + 3] = value & 0xff;
} else {
buffer.parent[buffer.offset + offset + 3] = (value >>> 24) & 0xff;
buffer.parent[buffer.offset + offset + 2] = (value >>> 16) & 0xff;
buffer.parent[buffer.offset + offset + 1] = (value >>> 8) & 0xff;
buffer.parent[buffer.offset + offset] = value & 0xff;
for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) {
buffer.parent[buffer.offset + offset + i] =
(value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff;
}
}

Expand Down
33 changes: 33 additions & 0 deletions test/buffer.js
Expand Up @@ -100,6 +100,39 @@ test("hex of write{Uint,Int}{8,16,32}{LE,BE}", function (t) {
t.end();
});

test("hex of write{Uint,Int}{8,16,32}{LE,BE} with overflow", function (t) {
t.plan(3*(2*2*2+2));
["UInt","Int"].forEach(function(x){
[8,16,32].forEach(function(y){
var endianesses = (y === 8) ? [""] : ["LE","BE"];
endianesses.forEach(function(z){
var v1 = new buffer.Buffer(y / 8 - 1);
var v2 = new Buffer(y / 8 - 1);
var next = new buffer.Buffer(4);
next.writeUInt32BE(0, 0);
var writefn = "write" + x + y + z;
var val = (x === "Int") ? -3 : 3;
v1[writefn](val, 0, true);
v2[writefn](val, 0, true);
t.equal(
v1.toString("hex"),
v2.toString("hex")
);
// check that nothing leaked to next buffer.
t.equal(next.readUInt32BE(0), 0);
// check that no bytes are read from next buffer.
next.writeInt32BE(~0, 0);
var readfn = "read" + x + y + z;
t.equal(
v1[readfn](0, true),
v2[readfn](0, true)
);
});
});
});
t.end();
});

test("concat() a varying number of buffers", function (t) {
t.plan(5);
var zero = [];
Expand Down

0 comments on commit 0504f9f

Please sign in to comment.