Closed Bug 520591 Opened 15 years ago Closed 15 years ago

"Assertion failure: invalid RECURSIVE_MISMATCH exit" with recursion

Categories

(Core :: JavaScript Engine, defect)

x86
macOS
defect
Not set
critical

Tracking

()

RESOLVED FIXED

People

(Reporter: jruderman, Assigned: dvander)

References

Details

(Keywords: assertion, regression, testcase, Whiteboard: fixed-in-tracemonkey)

Attachments

(4 files)

Attached file fragile testcase
With hg rev 9adc8fa19990+, this fragile testcase triggers an assertion failure.  It's so fragile I can't even reproduce under Valgrind!

~/tracemonkey/js/src/debug/js -j f1.js 

Assertion failure: invalid RECURSIVE_MISMATCH exit, at ../jsrecursion.cpp:72
WFM, tracemonkey rev 814e6dd2c1a3+.
Status: NEW → RESOLVED
Closed: 15 years ago
Resolution: --- → WORKSFORME
Status: RESOLVED → REOPENED
Resolution: WORKSFORME → ---
$ cat 1testcase.js 
function() {}
try { (function() { (function() {
            t1
        })
    })
} catch(e) {}
function() {}
function() {}
function() {}
(function() { (x
        for (x in []) if (3))
    })
function() {}
function() {}
function() {}
function() {}
function() {}
function() {}
(function() { ((function() {
            (function() { [ou] } [MI], 0)
        })(el))
    })
try { (function() {
        for (a = 1; a < 6; ++a) {
            if (a == 0) {} else {
                print((function sum_slicing(aaaaaa) {
                    return aaaaaa.length == 0 ? 0 : aaaaaa[0] + sum_slicing(aaaaaa.slice(1))
                })(['', (0), (0), (0), (0), (0), 'AA', (-0), null, (-1)]))
            }
        }
    })()
} catch(e) {}
try { (function() {})() } catch(e) {}
try { (function() { (function foo(bbbbbb) {
            if (bbbbbb < 1) {
                return 1
            }
            return foo(bbbbbb - 1) + foo(bbbbbb - 2)
        })(6)
    })()
} catch(e) {}
$ ./js-dbg-tm-darwin -j 1testcase.js 
00000AA-1
00000AA-1
00000AA-1
00000AA-1
00000AA-1
Assertion failure: invalid RECURSIVE_MISMATCH exit, at ../jsrecursion.cpp:72
Trace/BPT trap
Status: REOPENED → NEW
Summary: "Assertion failure: invalid RECURSIVE_MISMATCH exit" → "Assertion failure: invalid RECURSIVE_MISMATCH exit" with recursion
I can reproduce this - interestingly, on x86 but not x64.
Attached patch fixSplinter Review
The purpose of this assert is to make sure that the FrameInfo that restored the stack has the same types as if we capture the stack again.

Problem is the Oracle can result in int32/double mismatches that are really harmless. The point of this assert is to catch the really bad things, like the stack height differing or a completely different JS type.
Assignee: general → dvander
Status: NEW → ASSIGNED
Attachment #404971 - Flags: review?(gal)
Comment on attachment 404971 [details] [diff] [review]
fix

>diff --git a/js/src/jsrecursion.cpp b/js/src/jsrecursion.cpp
>--- a/js/src/jsrecursion.cpp
>+++ b/js/src/jsrecursion.cpp
>@@ -62,18 +62,20 @@ AssertDownFrameIsConsistent(JSContext* c
>     unsigned downPostSlots = fi->callerHeight;
>     JSTraceType* typeMap = fi->get_typemap();
> 
>     js_CaptureStackTypes(cx, 1, typeMap);
>     const JSTraceType* m1 = anchor->recursive_down->get_typemap();
>     for (unsigned i = 0; i < downPostSlots; i++) {
>         if (m1[i] == typeMap[i])
>             continue;
>-        if (typeMap[i] == TT_INT32 && m1[i] == TT_DOUBLE)
>+        if (typeMap[i] == TT_INT32 && m1[i] == TT_DOUBLE ||
>+            typeMap[i] == TT_DOUBLE && m1[i] == TT_INT32) {
>             continue;

Copy into temporaries please. It read over and over from the array.

>+        }
>         JS_NOT_REACHED("invalid RECURSIVE_MISMATCH exit");
>     }
>     JS_ASSERT(memcmp(anchor->recursive_down, fi, sizeof(FrameInfo)) == 0);
> }
> #endif
> 
> JS_REQUIRES_STACK VMSideExit*
> TraceRecorder::downSnapshot(FrameInfo* downFrame)
>diff --git a/js/src/trace-test/tests/basic/testBug520591.js b/js/src/trace-test/tests/basic/testBug520591.js
>new file mode 100644
>--- /dev/null
>+++ b/js/src/trace-test/tests/basic/testBug520591.js
>@@ -0,0 +1,45 @@
>+function() {}
>+try { (function() { (function() {
>+            t1
>+        })
>+    })
>+} catch(e) {}
>+function() {}
>+function() {}
>+function() {}
>+(function() { (x
>+        for (x in []) if (3))
>+    })
>+function() {}
>+function() {}
>+function() {}
>+function() {}
>+function() {}
>+function() {}
>+(function() { ((function() {
>+            (function() { [ou] } [MI], 0)
>+        })(el))
>+    })
>+try { (function() {
>+        for (a = 1; a < 6; ++a) {
>+            if (a == 0) {} else {
>+                print((function sum_slicing(aaaaaa) {
>+                    return aaaaaa.length == 0 ? 0 : aaaaaa[0] +
>+sum_slicing(aaaaaa.slice(1))
>+                })(['', (0), (0), (0), (0), (0), 'AA', (-0), null, (-1)]))
>+            }
>+        }
>+    })()
>+} catch(e) {}
>+try { (function() {})() } catch(e) {}
>+try { (function() { (function foo(bbbbbb) {
>+            if (bbbbbb < 1) {
>+                return 1
>+            }
>+            return foo(bbbbbb - 1) + foo(bbbbbb - 2)
>+        })(6)
>+    })()
>+} catch(e) {}
>+
>+/* Don't assert */
>+
Attachment #404971 - Flags: review?(gal) → review+
Thats one awesome testcase. Thanks jesse for teaching the fuzzer about recursion so quickly.
http://hg.mozilla.org/mozilla-central/rev/140346641114
Status: ASSIGNED → RESOLVED
Closed: 15 years ago15 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: