Closed Bug 1212296 Opened 6 years ago Closed 6 years ago

Assertion failure: !hasUncompiledScript(), at js/src/shell/../jsfun.h:422 with OOM

Categories

(Core :: JavaScript Engine, defect)

x86_64
Linux
defect
Not set
critical

Tracking

()

RESOLVED FIXED
mozilla44
Tracking Status
firefox44 --- fixed

People

(Reporter: decoder, Assigned: lth)

References

(Blocks 1 open bug)

Details

(Keywords: assertion, regression, testcase, Whiteboard: [jsbugmon:])

Attachments

(1 file, 1 obsolete file)

The following testcase crashes on mozilla-central revision 67adec79eb8a (build with --enable-optimize --enable-posix-nspr-emulation --enable-valgrind --enable-gczeal --disable-tests --enable-debug, run with --fuzzing-safe --thread-count=2):

const verbose = false;
if (!("oomAtAllocation" in this && "resetOOMFailure" in this))
    quit();
if ("gczeal" in this)
    gczeal(0);
function oomTest(f) {
    var i = 1;
    var more;
    do {
        if (verbose)
            print("fail at " + i);
        try {
            oomAtAllocation(i);
            f();
            more = resetOOMFailure();
        } catch (e) {
            more = resetOOMFailure();
        }
        i++;
    } while(more);

    if (verbose)
        print("finished after " + i);
}
var lfcode = new Array();
lfcode.push = loadFile;
lfcode.push("1");
oomTest(() => {
    if (Number.isFinite(NaN) << (this) << (this) == 99)
        throw "foo";
});
function loadFile(lfVarx) {
    if (lfVarx.substr(-3) != ".js" && lfVarx.length != 1) {} else if (!isNaN(lfVarx)) {}
}



Backtrace:

Program received signal SIGSEGV, Segmentation fault.
0x00000000004275a0 in JSFunction::nonLazyScript (this=<optimized out>) at js/src/shell/../jsfun.h:422
#0  0x00000000004275a0 in JSFunction::nonLazyScript (this=<optimized out>) at js/src/shell/../jsfun.h:422
#1  0x00000000004919d8 in nonLazyScript (this=<optimized out>) at js/src/shell/../jsfun.h:422
#2  JSFunction::getOrCreateScript (this=<optimized out>, cx=<optimized out>) at js/src/shell/../jsfun.h:385
#3  0x000000000070669a in js::Invoke (cx=cx@entry=0x7ffff6907400, args=..., construct=construct@entry=js::NO_CONSTRUCT) at js/src/vm/Interpreter.cpp:771
#4  0x00000000006f84a9 in Interpret (cx=cx@entry=0x7ffff6907400, state=...) at js/src/vm/Interpreter.cpp:3072
#5  0x0000000000705e73 in js::RunScript (cx=cx@entry=0x7ffff6907400, state=...) at js/src/vm/Interpreter.cpp:709
#6  0x000000000070674f in js::Invoke (cx=cx@entry=0x7ffff6907400, args=..., construct=construct@entry=js::NO_CONSTRUCT) at js/src/vm/Interpreter.cpp:786
#7  0x00000000006f84a9 in Interpret (cx=cx@entry=0x7ffff6907400, state=...) at js/src/vm/Interpreter.cpp:3072
#8  0x0000000000705e73 in js::RunScript (cx=cx@entry=0x7ffff6907400, state=...) at js/src/vm/Interpreter.cpp:709
#9  0x000000000070bef4 in js::ExecuteKernel (cx=cx@entry=0x7ffff6907400, script=..., script@entry=..., scopeChainArg=..., thisv=..., newTargetValue=..., type=<optimized out>, evalInFrame=evalInFrame@entry=..., result=result@entry=0x0) at js/src/vm/Interpreter.cpp:983
#10 0x000000000070c249 in js::Execute (cx=cx@entry=0x7ffff6907400, script=script@entry=..., scopeChainArg=..., rval=rval@entry=0x0) at js/src/vm/Interpreter.cpp:1018
#11 0x0000000000b7662b in ExecuteScript (cx=cx@entry=0x7ffff6907400, scope=..., script=..., rval=rval@entry=0x0) at js/src/jsapi.cpp:4453
#12 0x0000000000b7674b in JS_ExecuteScript (cx=cx@entry=0x7ffff6907400, scriptArg=..., scriptArg@entry=...) at js/src/jsapi.cpp:4484
#13 0x0000000000428676 in RunFile (compileOnly=false, file=0x7ffff699c800, filename=0x7fffffffe1b9 "min.js", cx=0x7ffff6907400) at js/src/shell/js.cpp:468
#14 Process (cx=cx@entry=0x7ffff6907400, filename=0x7fffffffe1b9 "min.js", forceTTY=forceTTY@entry=false) at js/src/shell/js.cpp:586
#15 0x0000000000477a62 in ProcessArgs (op=0x7fffffffdb70, cx=0x7ffff6907400) at js/src/shell/js.cpp:5923
#16 Shell (envp=<optimized out>, op=0x7fffffffdb70, cx=0x7ffff6907400) at js/src/shell/js.cpp:6223
#17 main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at js/src/shell/js.cpp:6579
rax	0x0	0
rbx	0x0	0
rcx	0x7ffff6ca588d	140737333844109
rdx	0x0	0
rsi	0x7ffff6f7a9d0	140737336814032
rdi	0x7ffff6f791c0	140737336807872
rbp	0x7fffffffc520	140737488340256
rsp	0x7fffffffc520	140737488340256
r8	0x7ffff7fcc780	140737353926528
r9	0x6372732f736a2f6c	7165916604736876396
r10	0x7fffffffc2e0	140737488339680
r11	0x7ffff6c27ee0	140737333329632
r12	0x7fffffffca20	140737488341536
r13	0x0	0
r14	0x2	2
r15	0x7ffff6907400	140737330050048
rip	0x4275a0 <JSFunction::nonLazyScript() const+28>
=> 0x4275a0 <JSFunction::nonLazyScript() const+28>:	movl   $0x1a6,0x0
   0x4275ab <JSFunction::nonLazyScript() const+39>:	callq  0x4979a0 <abort()>


We have that assertion already on file, but this one looks different to the other bug we already have.
Whiteboard: [jsbugmon:update,bisect] → [jsbugmon:bisect]
JSBugMon: Cannot process bug: Unable to automatically reproduce, please track manually.
Whiteboard: [jsbugmon:bisect] → [jsbugmon:]
Repro on Mac OS X from oom branch.

Also with --no-threads --no-baseline --no-ion.
Also in debug builds.
A patch is on the oom branch.
Assignee: nobody → lhansen
This is a local fix that works for me, but I see nonLazyScript() being called many other places too, and it's plausible that those calls could have the same problem, probably depends on many factors.
Attachment #8670815 - Flags: review?(till)
Till says "my guess is that we're not re-setting the INTERPRETED_LAZY on compilation failure" and to look to similar problems in https://bugzilla.mozilla.org/show_bug.cgi?id=1188347.
The following is possibly the culprit: in the "else", the attribute bits on fun are not reset.

In js::CloneScriptIntoFunction:

    if (!detail::CopyScript(cx, fun, src, dst)) {
        if (lazy)
            fun->initLazyScript(lazy);
        else
            fun->setScript(nullptr);
        return nullptr;
    }

(Code introduced by bug 1188347.)

Don't know how the bits should be set yet though, or whether they should be set here or in setScript.
Resetting the attribute bits just moves the error since !interpreted == native.  More likely the clone failure does not reset the necessary function(?) state higher up.
The early linking of function and destination script alters the flags of the function.  Set them back to what they were if we have to back out due to OOM.
Attachment #8670815 - Attachment is obsolete: true
Attachment #8670815 - Flags: review?(till)
Attachment #8671037 - Flags: review?(till)
Comment on attachment 8671037 [details] [diff] [review]
Undo flag changes if we back out for OOM

Review of attachment 8671037 [details] [diff] [review]:
-----------------------------------------------------------------

Good catch, thanks.

::: js/src/jsscript.cpp
@@ +3560,5 @@
>          fun->initScript(dst);
>      }
>  
>      if (!detail::CopyScript(cx, fun, src, dst)) {
>          if (lazy)

Nit: braces for all branches if one requires them.

Also, perhaps add a MOZ_ASSERT(fun->flags() == preservedFlags) to this branch? Just in case some future change makes the flag mutations not symmetric between setUnlazifiedScript and initLazyScript.
Attachment #8671037 - Flags: review?(till) → review+
https://hg.mozilla.org/mozilla-central/rev/50ca52df7917
Status: NEW → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla44
You need to log in before you can comment on or make changes to this bug.