Bug 814761 - Part 2/2: add test cases, r=rwood,yoshi
authorRob Wood <rwood@mozilla.com>
Mon, 10 Dec 2012 14:19:42 +0800
changeset 124571 957e9d5fe527d6bea6d141bc1864f42b443c51de
parent 124570 4130f20282defdcdc61c2a8c5fc2041396f5fe4c
child 124572 263bc2e3481f954ce40127fdc5e8e3520025d0cb
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrwood, yoshi
bugs814761
milestone20.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 814761 - Part 2/2: add test cases, r=rwood,yoshi
dom/sms/tests/marionette/manifest.ini
dom/sms/tests/marionette/test_bug814761.js
dom/system/gonk/tests/test_ril_worker_buf.js
--- a/dom/sms/tests/marionette/manifest.ini
+++ b/dom/sms/tests/marionette/manifest.ini
@@ -19,8 +19,9 @@ qemu = true
 ;[test_filter_number_multiple.js]
 [test_filter_received.js]
 [test_filter_sent.js]
 [test_filter_read.js]
 [test_filter_unread.js]
 [test_number_of_messages.js]
 [test_mark_msg_read.js]
 [test_mark_msg_read_error.js]
+[test_bug814761.js]
new file mode 100644
--- /dev/null
+++ b/dom/sms/tests/marionette/test_bug814761.js
@@ -0,0 +1,70 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 20000;
+
+SpecialPowers.setBoolPref("dom.sms.enabled", true);
+SpecialPowers.addPermission("sms", true, document);
+
+let sms = window.navigator.mozSms;
+
+// Note: 378 chars and below is fine, but 379 and above will cause the issue.
+// Sending first message works, but second one we get emulator callback but
+// the actual SMS is never received, so script will timeout waiting for the
+// sms.onreceived event. Also note that a single larger message (i.e. 1600
+// characters) works; so it is not a compounded send limit.
+let fromNumber = "5551110000";
+let msgLength = 379;
+let msgText = new Array(msgLength + 1).join('a');
+
+let pendingEmulatorCmdCount = 0;
+function sendSmsToEmulator(from, text) {
+  ++pendingEmulatorCmdCount;
+
+  let cmd = "sms send " + from + " " + text;
+  runEmulatorCmd(cmd, function (result) {
+    --pendingEmulatorCmdCount;
+
+    is(result[0], "OK", "Emulator response");
+  });
+}
+
+function firstIncomingSms() {
+  simulateIncomingSms(secondIncomingSms);
+}
+
+function secondIncomingSms() {
+  simulateIncomingSms(cleanUp);
+}
+
+function simulateIncomingSms(nextFunction) {
+  log("Simulating incoming multipart SMS (" + msgText.length
+      + " chars total).");
+
+  sms.onreceived = function onreceived(event) {
+    log("Received 'onreceived' smsmanager event.");
+    sms.onreceived = null;
+
+    let incomingSms = event.message;
+    ok(incomingSms, "incoming sms");
+    is(incomingSms.body, msgText, "msg body");
+
+    window.setTimeout(nextFunction, 0);
+  };
+
+  sendSmsToEmulator(fromNumber, msgText);
+}
+
+function cleanUp() {
+  if (pendingEmulatorCmdCount) {
+    window.setTimeout(cleanUp, 100);
+    return;
+  }
+
+  SpecialPowers.removePermission("sms", document);
+  SpecialPowers.clearUserPref("dom.sms.enabled");
+  finish();
+}
+
+// Start the test
+firstIncomingSms();
--- a/dom/system/gonk/tests/test_ril_worker_buf.js
+++ b/dom/system/gonk/tests/test_ril_worker_buf.js
@@ -77,16 +77,91 @@ add_test_incoming_parcel(null,
 
     do_check_throws(function over_read_handler() {
       // reads more than parcel size, should throw an error.
       buf.readUint8();
     },"Trying to read data beyond the parcel end!");
   }
 );
 
+// Test Bug 814761: buffer overwritten
+add_test(function test_incoming_parcel_buffer_overwritten() {
+  let worker = newWorker({
+    postRILMessage: function fakePostRILMessage(data) {
+      // do nothing
+    },
+    postMessage: function fakePostMessage(message) {
+      // do nothing
+    }
+  });
+
+  // A convenient alias.
+  let buf = worker.Buf;
+
+  // Allocate an array of specified size and set each of its elements to value.
+  function calloc(length, value) {
+    let array = new Array(length);
+    for (let i = 0; i < length; i++) {
+      array[i] = value;
+    }
+    return array;
+  }
+
+  // Do nothing in handleParcel().
+  let request = worker.REQUEST_REGISTRATION_STATE;
+  worker.RIL[request] = null;
+
+  // Prepare two parcels, whose sizes are both smaller than the incoming buffer
+  // size but larger when combined, to trigger the bug.
+  let pA_dataLength = buf.INCOMING_BUFFER_LENGTH / 2;
+  let pA = newIncomingParcel(-1,
+                             worker.RESPONSE_TYPE_UNSOLICITED,
+                             request,
+                             calloc(pA_dataLength, 1));
+  let pA_parcelSize = pA.length - worker.PARCEL_SIZE_SIZE;
+
+  let pB_dataLength = buf.INCOMING_BUFFER_LENGTH * 3 / 4;
+  let pB = newIncomingParcel(-1,
+                             worker.RESPONSE_TYPE_UNSOLICITED,
+                             request,
+                             calloc(pB_dataLength, 1));
+  let pB_parcelSize = pB.length - worker.PARCEL_SIZE_SIZE;
+
+  // First, send an incomplete pA and verifies related data pointer:
+  let p1 = pA.subarray(0, pA.length - 1);
+  worker.onRILMessage(p1);
+  // The parcel should not have been processed.
+  do_check_eq(buf.readAvailable, 0);
+  // buf.currentParcelSize should have been set because incoming data has more
+  // than 4 octets.
+  do_check_eq(buf.currentParcelSize, pA_parcelSize);
+  // buf.readIncoming should contains remaining unconsumed octets count.
+  do_check_eq(buf.readIncoming, p1.length - worker.PARCEL_SIZE_SIZE);
+  // buf.incomingWriteIndex should be ready to accept the last octet.
+  do_check_eq(buf.incomingWriteIndex, p1.length);
+
+  // Second, send the last octet of pA and whole pB. The Buf should now expand
+  // to cover both pA & pB.
+  let p2 = new Uint8Array(1 + pB.length);
+  p2.set(pA.subarray(pA.length - 1), 0);
+  p2.set(pB, 1);
+  worker.onRILMessage(p2);
+  // The parcels should have been both consumed.
+  do_check_eq(buf.readAvailable, 0);
+  // No parcel data remains.
+  do_check_eq(buf.currentParcelSize, 0);
+  // No parcel data remains.
+  do_check_eq(buf.readIncoming, 0);
+  // The Buf should now expand to cover both pA & pB.
+  do_check_eq(buf.incomingWriteIndex, pA.length + pB.length);
+
+  // end of incoming parcel's trip, let's do next test.
+  run_next_test();
+});
+
 // Test Buf.readUint8Array.
 add_test_incoming_parcel(null,
   function test_buf_readUint8Array(worker) {
     let buf = worker.Buf;
 
     let u8array = buf.readUint8Array(1);
     do_check_eq(u8array instanceof Uint8Array, true);
     do_check_eq(u8array.length, 1);