Bug 723244 - RIL: implement parcel length guards. r=philikon
authorVicamo Yang <vyang@mozilla.com>
Mon, 20 Feb 2012 19:30:04 +0100
changeset 87236 9d17d2dc9754e3872d92569874783bfec665ed04
parent 87235 09072cd32bb924b12b4a27ce09324def9ad76163
child 87237 d25397e8464594b73e349c13055f5975c70aec05
push id22103
push userbmo@edmorley.co.uk
push dateTue, 21 Feb 2012 12:01:45 +0000
treeherdermozilla-central@4038ffaa5d82 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersphilikon
bugs723244
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 723244 - RIL: implement parcel length guards. r=philikon
dom/system/b2g/ril_worker.js
--- a/dom/system/b2g/ril_worker.js
+++ b/dom/system/b2g/ril_worker.js
@@ -103,16 +103,19 @@ let Buf = {
     this.incomingReadIndex = 0;
 
     // Leave room for the parcel size for outgoing parcels.
     this.outgoingIndex = PARCEL_SIZE_SIZE;
 
     // How many bytes we've read for this parcel so far.
     this.readIncoming = 0;
 
+    // How many bytes available as parcel data.
+    this.readAvailable = 0;
+
     // Size of the incoming parcel. If this is zero, we're expecting a new
     // parcel.
     this.currentParcelSize = 0;
 
     // This gets incremented each time we send out a parcel.
     this.token = 1;
 
     // Maps tokens we send out with requests to the request type, so that
@@ -187,23 +190,32 @@ let Buf = {
   },
 
   /**
    * Functions for reading data from the incoming buffer.
    *
    * These are all little endian, apart from readParcelSize();
    */
 
-  readUint8: function readUint8() {
+  readUint8Unchecked: function readUint8Unchecked() {
     let value = this.incomingBytes[this.incomingReadIndex];
     this.incomingReadIndex = (this.incomingReadIndex + 1) %
                              this.INCOMING_BUFFER_LENGTH;
     return value;
   },
 
+  readUint8: function readUint8() {
+    if (!this.readAvailable) {
+      throw new Error("Trying to read data beyond the parcel end!");
+    }
+
+    this.readAvailable--;
+    return this.readUint8Unchecked();
+  },
+
   readUint16: function readUint16() {
     return this.readUint8() | this.readUint8() << 8;
   },
 
   readUint32: function readUint32() {
     return this.readUint8()       | this.readUint8() <<  8 |
            this.readUint8() << 16 | this.readUint8() << 24;
   },
@@ -246,18 +258,20 @@ let Buf = {
     let strings = [];
     for (let i = 0; i < num_strings; i++) {
       strings.push(this.readString());
     }
     return strings;
   },
 
   readParcelSize: function readParcelSize() {
-    return this.readUint8() << 24 | this.readUint8() << 16 |
-           this.readUint8() <<  8 | this.readUint8();
+    return this.readUint8Unchecked() << 24 |
+           this.readUint8Unchecked() << 16 |
+           this.readUint8Unchecked() <<  8 |
+           this.readUint8Unchecked();
   },
 
   /**
    * Functions for writing data to the outgoing buffer.
    */
 
   writeUint8: function writeUint8(value) {
     if (this.outgoingIndex >= this.OUTGOING_BUFFER_LENGTH) {
@@ -407,47 +421,47 @@ let Buf = {
           parcel = Array.slice(this.incomingBytes.subarray(
             this.incomingReadIndex, expectedAfterIndex));
         }
         debug("Parcel (size " + this.currentParcelSize + "): " + parcel);
       }
 
       if (DEBUG) debug("We have at least one complete parcel.");
       try {
+        this.readAvailable = this.currentParcelSize;
         this.processParcel();
       } catch (ex) {
         if (DEBUG) debug("Parcel handling threw " + ex + "\n" + ex.stack);
       }
 
       // Ensure that the whole parcel was consumed.
       if (this.incomingReadIndex != expectedAfterIndex) {
         if (DEBUG) {
           debug("Parcel handler didn't consume whole parcel, " +
                 Math.abs(expectedAfterIndex - this.incomingReadIndex) +
                 " bytes left over");
         }
         this.incomingReadIndex = expectedAfterIndex;
       }
       this.readIncoming -= this.currentParcelSize;
+      this.readAvailable = 0;
       this.currentParcelSize = 0;
     }
   },
 
   /**
    * Process one parcel.
    */
   processParcel: function processParcel() {
     let response_type = this.readUint32();
-    let length = this.readIncoming - UINT32_SIZE;
 
     let request_type, options;
     if (response_type == RESPONSE_TYPE_SOLICITED) {
       let token = this.readUint32();
       let error = this.readUint32();
-      length -= 2 * UINT32_SIZE;
 
       options = this.tokenRequestMap[token];
       request_type = options.rilRequestType;
       if (error) {
         //TODO
         if (DEBUG) {
           debug("Received error " + error + " for solicited parcel type " +
                 request_type);
@@ -457,24 +471,23 @@ let Buf = {
       if (DEBUG) {
         debug("Solicited response for request type " + request_type +
               ", token " + token);
       }
       delete this.tokenRequestMap[token];
       this.lastSolicitedToken = token;
     } else if (response_type == RESPONSE_TYPE_UNSOLICITED) {
       request_type = this.readUint32();
-      length -= UINT32_SIZE;
       if (DEBUG) debug("Unsolicited response for request type " + request_type);
     } else {
       if (DEBUG) debug("Unknown response type: " + response_type);
       return;
     }
 
-    RIL.handleParcel(request_type, length, options);
+    RIL.handleParcel(request_type, this.readAvailable, options);
   },
 
   /**
    * Start a new outgoing parcel.
    *
    * @param type
    *        Integer specifying the request type.
    * @param options [optional]