Closed Bug 152646 Opened 22 years ago Closed 21 years ago

Too many parentheses in JavaScript expression causes crash

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
critical

Tracking

()

VERIFIED DUPLICATE of bug 192414

People

(Reporter: security-bugs, Unassigned)

Details

(Keywords: crash, testcase)

Attachments

(3 files)

The JS engine crashes when evaluating an expression with too many parentheses.

var a = ((((((((((((... a few hundred more ... ((( ))) ... and a few hundred of
these ... ))))):

This causes the stack to overflow. Here's a stack trace of one cycle in the
recursion:

BitAndExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2258 + 17 bytes
BitXorExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2245 + 17 bytes
BitOrExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2232 + 17 bytes
AndExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2221 + 17 bytes
OrExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2210 + 17 bytes
CondExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2170 + 17 bytes
AssignExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2116 + 17 bytes
Expr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2090 + 17 bytes
PrimaryExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2898 + 17 bytes
MemberExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8, int 1) line 2580 + 17 bytes
UnaryExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2498 + 19 bytes
MulExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2360 + 17 bytes
AddExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2342 + 17 bytes
ShiftExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2327 + 17 bytes
RelExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2295 + 17 bytes
EqExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2270 + 17 bytes
BitAndExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2258 + 17 bytes
BitXorExpr(JSContext * 0x03846028, JSTokenStream * 0x03be6130, JSTreeContext *
0x0012efc8) line 2245 + 17 bytes
BitOrExpr(JSContext... and so on

This does not appear to be an exploitable buffer overrun, merely a stack
overflow from too much recursion. This appears related to bug 96526, so I'm
assigning it to Kenton.
I see this [Mozilla 2002061712, Windows 2000]

Talkback ID: TB7475581E
Summary: Too many parens in expression causes a crash → Too many parentheses in JavaScript expression causes crash
I see this [Netscape4.79, Windows 2000]

Talkback ID: TB747032E
Severity: normal → critical
Keywords: crash, testcase
This is not recursion.  This is expression complexity.  

Elimination of unnecessary parentheses at the parsing stage is a possible
solution.  
I looked up both Talkback incidents above, TB7475581E and TB747032E.
Simple stack overflow in the former, and no stack for the latter.
Testcase added to JS testsuite:

          mozilla/js/tests/js1_5/Regress/regress-152646.js
I check the callstack, I find that the recursive call of the next function
cause the stack overflow and crash.

    MulExpr() line 2360
    AddExpr() line 2342 + 17 bytes
    ShiftExpr() line 2327 + 17 bytes
    RelExpr() line 2295 + 17 bytes
    EqExpr() line 2270 + 17 bytes
    BitAndExpr() line 2258 + 17 bytes
    BitXorExpr() line 2245 + 17 bytes
    BitOrExpr() line 2232 + 17 bytes
    AndExpr() line 2221 + 17 bytes
    OrExpr() line 2210 + 17 bytes
    CondExpr() line 2170 + 17 bytes
    AssignExpr() line 2116 + 17 bytes
    Expr() line 2090 + 17 bytes
    PrimaryExpr() line 2898 + 17 bytes
    MemberExpr() line 2580 + 17 bytes
    UnaryExpr() line 2498 + 19 bytes

    when it parse too many "((((( ... (((" in the testcase.Mozilla use the
recursive call. I suggest mozilla should add a limit to avoid recursive call
too deep and avoid stack overflow.
I add a limit to avoid the recursive call too deep. This patch worked well
for the testcase and didn't affect others.
Comment on attachment 90757 [details] [diff] [review]
a suggest patch for review

Sorry, using a static is not thread-safe.  Also, returning NULL without
reporting an error is bad form: it silently kills compilation without telling
the user why.

I think this bug is better addressed by avoiding recursion on the C stack. 
khanson may have some thoughts.

/be
Attachment #90757 - Flags: needs-work+
I don’t understand why this is marked critical.  No real world example has been
presented.  Why would anyone surround an expression with hundreds of enclosing
parenthesis?  I will continue to look for a solution.
Attachment 90757 [details] [diff] prevents a crash, but, what is the correct limit for the number
of nested parenthesis?  It varies from machine to machine and is dependant on
its embedding within the javascrpt program.  Does anyone have any suggestions
for stack sniffing routines for dynamically determining when the stack space is
getting low?
I see no comment from aha@pinknet.cz justifying the severity change.  Severity
is for reporters to set, so I'm restoring mstoltz's initial severity.

I agree with khanson that this is not a high-priority bug to work on right now.
 JS stack overflow hazards ought to be addressed systematically, too.  E.g., all
recursive procedures should have tuned or self-tuning limits, or should be
converted to iterative procedures.

/be
Severity: critical → normal
Kenton, Brendan: I marked this as critical because it's causing crash. I'm
sorry, change was IMHO correct according to impact scale in 'A Bug's Life Cycle'
document.
aha: sorry, a crash that never happens in practice cannot be critical.

Asa, Gerv: does the bug life cycle doc need more nuance?

/be
Well, it requires the application of common-sense when reading it :-)

Unsurprisingly, our website is so disorganised that I can't find that document.
Can someone post the URL?

Gerv
Gerv: http://bugzilla.mozilla.org/bug_status.html#severity
Brendan, Gerv: I'm sorry, it was half-automatic action while reading new bugs.
Low priority due to its rare occurrence in real JavasScript programs. 
Preprocessing scripts to eliminate unnecessary parenthesis seems a bit
burdensome for scripts without this unnatural defect.  The proposed patch, while
avoiding crashes, puts an arbitrary limit on parenthesis depth, a limit that
should vary dynamically with platforms and script complexity.  I am still
looking for a methodology for dynamically detecting low stack conditions.  Any
suggestions?
By the definitions on <http://bugzilla.mozilla.org/bug_status.html#severity> and
<http://bugzilla.mozilla.org/enter_bug.cgi?format=guided>, crashing and dataloss
bugs are of critical or possibly higher severity.  Only changing open bugs to
minimize unnecessary spam.  Keywords to trigger this would be crash, topcrash,
topcrash+, zt4newcrash, dataloss.
Severity: normal → critical
Right: suppose someone is browsing, in the middle of ordering from
Amazon.com--then they open another web page with 1000 parentheses in JavaScript,
and it crashes everything. Therefore, by application, anything that makes a
crash should be considered critical.
We really should scrap the emotionally charged "Priority" label (avoiding fights
over whose priority it is) and replace it with a less subjective
"frequency/visibility" field. 

Do any developers really use the Priority field to manage their work?
Brendan pointed out to me that this bug and bug 192414 are duplicates.
Since more comments and patches have occurred on the latter bug, I am
going to dupe this one forward.

Anyone interested in following progress on this issue should cc himself
on bug 192414, "Parser recursion does not check stack overflow" -

*** This bug has been marked as a duplicate of 192414 ***
Status: NEW → RESOLVED
Closed: 21 years ago
Resolution: --- → DUPLICATE
Verified Duplicate -
Status: RESOLVED → VERIFIED
Test results, smdebug

Test List: All tests
Skip List: lc2, lc3
1112 test(s) selected, 1112 test(s) completed, 6 failures reported (0.53% failed)
Engine command line: .\..\src\WINNT5.0_DBG.OBJ\js.exe
OS type: WIN
Testcase execution time: 14 minutes, 10 seconds.
Tests completed on Fri Nov 7 13:44:01 2003.

CVS is from between 10/21 and 10/27 based on cvs status for jsapi.h.

    Testcase js1_5/Regress/regress-152646.js failed
    [ Previous Failure | Next Failure | Top of Page ]
    Expected exit code 0, got 253
    Testcase terminated with signal 0
    Complete testcase output was:
    Testcase produced no output!
Status: VERIFIED → REOPENED
Resolution: DUPLICATE → ---
perhaps a new bug needs to be filed based on bug 192414 comment 29, bug 192414
comment 31, bug 192414 comment 32 for smdebug?

phil: could you possibly change the test files so that they point to a live bug
instead of a dead bug? running through the regression test suite and getting
failures is really confusing for me when i'm tired / rushed / distracted.

sorry about the reopen.
Assignee: khanson → general
Status: REOPENED → NEW
timeless: I'm also failing on js1_5/Regress/regress-192414.js, 
in both the debug and optimized JS shell on WinNT.

Are you failing on that one, too?

Each testcase is named after the bug it was written for, and
points to that bug for the most thorough historical context.
yeah i'm failing that one too
Shouldn't we reopen bug 192414, then, which this one had been duped against?

I'm going to go ahead and do that if no one minds: re-resolve this bug as
a dupe, and re-open bug 192414, since most of the work occurred there -

*** This bug has been marked as a duplicate of 192414 ***
Status: NEW → RESOLVED
Closed: 21 years ago21 years ago
Resolution: --- → DUPLICATE
Re-marking Verified Duplicate.

timeless: thanks for finding this; I have cc'ed you on bug 192414 -
Status: RESOLVED → VERIFIED
Flags: testcase+
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: