]> zoso.dev Git - buffer.git/commitdiff
Fix overflow issues on writing/reading integers
authorTõnis Tiigi <tonistiigi@gmail.com>
Wed, 27 Feb 2013 14:25:49 +0000 (16:25 +0200)
committerTõnis Tiigi <tonistiigi@gmail.com>
Wed, 27 Feb 2013 19:43:34 +0000 (21:43 +0200)
index.js
test/buffer.js

index 522dd9358a2c671bedc1e35b35294d30d4b00b47..bf28833eeed32155d35a9005b49469fe5fcd6be4 100644 (file)
--- a/index.js
+++ b/index.js
@@ -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];
 };
 
@@ -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;
@@ -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;
@@ -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]);
@@ -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) {
@@ -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) {
@@ -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;
   }
 }
 
index f54c5d2508466db4c27a423ac72c8faa073c8059..5745cdf757d2f11101f2eb0637c1181068b6f7b4 100644 (file)
@@ -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 = [];