Bug 1215363 - Fix a couple of OOM handling issues and make JS_sprintf funcions crash when passed illegal format strings r=terrence
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 20 Oct 2015 10:29:46 +0100
changeset 303674 6f1f7fc0f7cd83db832072eb05d316845c6f3930
parent 303673 6f1ff0ce8b6b55f8d366c820af2f1973820b7fff
child 303675 da38bd42a863a6b3228500912a1bb2766ff79166
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1215363
milestone44.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 1215363 - Fix a couple of OOM handling issues and make JS_sprintf funcions crash when passed illegal format strings r=terrence
js/src/jit-test/tests/gc/bug-1215363-1.js
js/src/jit-test/tests/gc/bug-1215363-2.js
js/src/jit-test/tests/gc/bug-1215363-3.js
js/src/jscntxt.cpp
js/src/jsprf.cpp
js/src/vm/ObjectGroup.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1215363-1.js
@@ -0,0 +1,4 @@
+if (!('oomTest' in this))
+    quit();
+
+oomTest(() => parseModule(10));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1215363-2.js
@@ -0,0 +1,7 @@
+if (!('oomTest' in this))
+    quit();
+
+var lfcode = new Array();
+oomTest((function(x) {
+    assertEq(...Object);
+}));
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1215363-3.js
@@ -0,0 +1,5 @@
+if (!('oomTest' in this))
+    quit();
+
+var lfcode = new Array();
+oomTest(() => getBacktrace({}));
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -427,18 +427,20 @@ js::ReportErrorVA(JSContext* cx, unsigne
     size_t messagelen;
     JSErrorReport report;
     bool warning;
 
     if (checkReportFlags(cx, &flags))
         return true;
 
     message = JS_vsmprintf(format, ap);
-    if (!message)
+    if (!message) {
+        ReportOutOfMemory(cx);
         return false;
+    }
     messagelen = strlen(message);
 
     report.flags = flags;
     report.errorNumber = JSMSG_USER_DEFINED_ERROR;
     report.ucmessage = ucmessage = InflateString(cx, message, &messagelen);
     PopulateReportBlame(cx, &report);
 
     warning = JSREPORT_IS_WARNING(report.flags);
--- a/js/src/jsprf.cpp
+++ b/js/src/jsprf.cpp
@@ -370,21 +370,21 @@ BuildArgArray(const char* fmt, va_list a
             continue;
         if ((c = *p++) == '%')          // skip %% case
             continue;
 
         while (c != 0) {
             if (c > '9' || c < '0') {
                 if (c == '$') {         // numbered argument case
                     if (i > 0)
-                        return false;
+                        MOZ_CRASH("Bad format string");
                     number++;
                 } else {                // non-numbered argument case
                     if (number > 0)
-                        return false;
+                        MOZ_CRASH("Bad format string");
                     i = 1;
                 }
                 break;
             }
 
             c = *p++;
         }
     }
@@ -412,41 +412,41 @@ BuildArgArray(const char* fmt, va_list a
 
         cn = 0;
         while (c && c != '$') {     // should improve error check later
             cn = cn*10 + c - '0';
             c = *p++;
         }
 
         if (!c || cn < 1 || cn > number)
-            return false;
+            MOZ_CRASH("Bad format string");
 
         // nas[cn] starts from 0, and make sure nas[cn].type is not assigned.
         cn--;
         if (nas[cn].type != TYPE_UNKNOWN)
             continue;
 
         c = *p++;
 
         // width
         if (c == '*') {
             // not supported feature, for the argument is not numbered
-            return false;
+            MOZ_CRASH("Bad format string");
         }
 
         while ((c >= '0') && (c <= '9')) {
             c = *p++;
         }
 
         // precision
         if (c == '.') {
             c = *p++;
             if (c == '*') {
                 // not supported feature, for the argument is not numbered
-                return false;
+                MOZ_CRASH("Bad format string");
             }
 
             while ((c >= '0') && (c <= '9')) {
                 c = *p++;
             }
         }
 
         // size
@@ -522,17 +522,17 @@ BuildArgArray(const char* fmt, va_list a
         default:
             MOZ_ASSERT(0);
             nas[cn].type = TYPE_UNKNOWN;
             break;
         }
 
         // get a legal para.
         if (nas[cn].type == TYPE_UNKNOWN)
-            return false;
+            MOZ_CRASH("Bad format string");
     }
 
 
     // Third pass:
     // Fill nas[].ap.
 
     cn = 0;
     while (cn < number) {
@@ -552,17 +552,17 @@ BuildArgArray(const char* fmt, va_list a
         case TYPE_UINT32:       (void) va_arg(ap, uint32_t);    break;
         case TYPE_INT64:        (void) va_arg(ap, int64_t);     break;
         case TYPE_UINT64:       (void) va_arg(ap, uint64_t);    break;
         case TYPE_STRING:       (void) va_arg(ap, char*);       break;
         case TYPE_WSTRING:      (void) va_arg(ap, char16_t*);   break;
         case TYPE_INTSTR:       (void) va_arg(ap, int*);        break;
         case TYPE_DOUBLE:       (void) va_arg(ap, double);      break;
 
-        default: return false;
+        default: MOZ_CRASH();
         }
 
         cn++;
     }
 
     return true;
 }
 
@@ -594,18 +594,17 @@ dosprintf(SprintfState* ss, const char* 
     const char* dolPt = nullptr;  // in "%4$.2f", dolPt will point to '.'
 
     // Build an argument array, IF the fmt is numbered argument
     // list style, to contain the Numbered Argument list pointers.
 
     NumArgStateVector nas;
     if (!BuildArgArray(fmt, ap, nas)) {
         // the fmt contains error Numbered Argument format, jliu@netscape.com
-        MOZ_ASSERT(0);
-        return false;
+        MOZ_CRASH("Bad format string");
     }
 
     while ((c = *fmt++) != 0) {
         if (c != '%') {
             if (!(*ss->stuff)(ss, fmt - 1, 1))
                 return false;
 
             continue;
@@ -628,17 +627,17 @@ dosprintf(SprintfState* ss, const char* 
             // the fmt contains the Numbered Arguments feature
             i = 0;
             while (c && c != '$') {         // should improve error check later
                 i = (i * 10) + (c - '0');
                 c = *fmt++;
             }
 
             if (nas[i - 1].type == TYPE_UNKNOWN)
-                return false;
+                MOZ_CRASH("Bad format string");
 
             ap = nas[i - 1].ap;
             dolPt = fmt;
             c = *fmt++;
         }
 
         // Examine optional flags.  Note that we do not implement the
         // '#' flag of sprintf().  The ANSI C spec. of the '#' flag is
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -1442,18 +1442,20 @@ ObjectGroup::allocationSiteGroup(JSConte
         PreliminaryObjectArrayWithTemplate* preliminaryObjects =
             cx->new_<PreliminaryObjectArrayWithTemplate>(nullptr);
         if (preliminaryObjects)
             res->setPreliminaryObjects(preliminaryObjects);
         else
             cx->recoverFromOutOfMemory();
     }
 
-    if (!table->add(p, key, res))
+    if (!table->add(p, key, res)) {
+        ReportOutOfMemory(cx);
         return nullptr;
+    }
 
     return res;
 }
 
 void
 ObjectGroupCompartment::replaceAllocationSiteGroup(JSScript* script, jsbytecode* pc,
                                                    JSProtoKey kind, ObjectGroup* group)
 {