Bug 763384 - Don't treat regexp syntax errors as OOM errors (r=njn)
authorLuke Wagner <luke@mozilla.com>
Mon, 11 Jun 2012 17:08:34 -0700
changeset 101313 15d7e7cc09a6fb6ee3deb38d460778ecdb8f0b8b
parent 101312 d7362d197229fadfe94f016139e731f12f4e7acb
child 101314 e781ec9cc4443e0c484d456861aff307ece6d695
push idunknown
push userunknown
push dateunknown
reviewersnjn
bugs763384
milestone16.0a1
Bug 763384 - Don't treat regexp syntax errors as OOM errors (r=njn)
js/public/Utility.h
js/src/jit-test/tests/basic/testBug763384.js
js/src/vm/RegExpObject.cpp
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -16,16 +16,17 @@
 #ifdef JS_OOM_DO_BACKTRACES
 #include <stdio.h>
 #include <execinfo.h>
 #endif
 
 #include "jstypes.h"
 
 #ifdef __cplusplus
+# include "mozilla/Scoped.h"
 
 /* The public JS engine namespace. */
 namespace JS {}
 
 /* The mozilla-shared reusable template/utility namespace. */
 namespace mozilla {}
 
 /* The private JS engine namespace. */
@@ -589,16 +590,25 @@ public:
     }
 
     JS_DECLARE_DELETE_METHODS(::js_free, JS_ALWAYS_INLINE static)
 };
 
 class UnwantedForeground : public Foreground {
 };
 
+template <typename T>
+struct ScopedDeletePtrTraits
+{
+    typedef T *type;
+    static T *empty() { return NULL; }
+    static void release(T *ptr) { Foreground::delete_(ptr); }
+};
+SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
+
 } /* namespace js */
 
 /*
  * Note lack of ; in JSRuntime below. This is intentional so "calling" this
  * looks "normal".
  */
 #define JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR \
     friend class js::OffTheBooks;\
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testBug763384.js
@@ -0,0 +1,9 @@
+var caught = false;
+try {
+    ''.match('(');
+} catch (e) {
+    caught = true;
+    assertEq(e instanceof Error, true);
+    assertEq(('' + e).indexOf('SyntaxError') === -1, false);
+}
+assertEq(caught, true);
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -555,39 +555,36 @@ RegExpCompartment::get(JSContext *cx, JS
 {
     Key key(keyAtom, flags, type);
     Map::AddPtr p = map_.lookupForAdd(key);
     if (p) {
         g->init(*p->value);
         return true;
     }
 
-    RegExpShared *shared = cx->runtime->new_<RegExpShared>(cx->runtime, flags);
+    ScopedDeletePtr<RegExpShared> shared(cx->new_<RegExpShared>(cx->runtime, flags));
     if (!shared)
-        goto error;
+        return false;
 
     if (!shared->compile(cx, source))
-        goto error;
+        return false;
 
     /* Re-lookup in case there was a GC. */
-    if (!map_.relookupOrAdd(p, key, shared))
-        goto error;
+    if (!map_.relookupOrAdd(p, key, shared)) {
+        js_ReportOutOfMemory(cx);
+        return false;
+    }
 
     /*
      * Since 'error' deletes 'shared', only guard 'shared' on success. This is
      * safe since 'shared' cannot be deleted by GC until after the call to
-     * map_.add() directly above.
+     * map_.relookupOrAdd() directly above.
      */
-    g->init(*shared);
+    g->init(*shared.forget());
     return true;
-
-  error:
-    Foreground::delete_(shared);
-    js_ReportOutOfMemory(cx);
-    return false;
 }
 
 bool
 RegExpCompartment::get(JSContext *cx, JSAtom *source, RegExpFlag flags, RegExpGuard *g)
 {
     return get(cx, source, source, flags, Normal, g);
 }