Closed Bug 366668 Opened 18 years ago Closed 18 years ago

Incorrect decompilation of "for (let x in x.p)"

Categories

(Core :: JavaScript Engine, defect)

PowerPC
macOS
defect
Not set
normal

Tracking

()

VERIFIED FIXED

People

(Reporter: jruderman, Assigned: mrbkap)

Details

(Keywords: testcase)

Attachments

(3 files, 2 obsolete files)

Decompilation incorrectly puts ".p" on the loop variable, causing a syntax error:

js> function() { for(let x in x.p) { } }   
function () {
    for (let x.p in x.p) {
    }
}

Toss in an assignment and it copies the entire assignment as well as sticking some extra .p's in:

js> function() { for(let x in (x = x.p)) { } } 
function () {
    for (let x.p = x.p in x.p = x.p) {
    }
}
js> function() { let (w) { with({x: w.something }) { } } }
function () {
    let (w) {
        with (mething, x:w.something}) {
        }
    }
}

Same bug?
Attached patch Proposed fix (obsolete) — Splinter Review
So, the problem here is the mini-optimization that JSOP_GETLOCALPROP does: it pushes an offset that's not at the end of the sprinter. As a result, the next time we push a string, SprintPut gets confused and overwrites whatever happened to be at the old location. This was causing the JSOP_INITPROP (and for-in) code to become unhappy when it looked at the stack for what was there before.

All other uses of PushOff refer to newly-Sprinted locations.
Assignee: general → mrbkap
Status: NEW → ASSIGNED
Attachment #252563 - Flags: review?(brendan)
Comment on attachment 252563 [details] [diff] [review]
Proposed fix

Those pesky non-top-most locals! Thanks,

/be
Attachment #252563 - Flags: review?(brendan) → review+
Attached patch Better fix, I think (obsolete) — Splinter Review
Here's the interdiff between the first and second patches:
               BEGIN_LITOPX_CASE(JSOP_GETLOCALPROP, 2)
                 i = GET_UINT16(pc);
                 LOCAL_ASSERT((uintN)i < ss->top);
-                lval = GetLocal(ss, i, JS_FALSE);
+                lval = GetLocal(ss, i, JS_TRUE);
                 if (!lval)
                     return NULL;
                 todo = SprintCString(&ss->sprinter, lval);

I think we need to retract, since we're Sprinting lval right after the GetLocal, but I'm not entirely sure I understand the retracting bit of the decompiler. Brendan, please tell me if this isn't needed.
Attachment #252563 - Attachment is obsolete: true
Attachment #252684 - Flags: review?(brendan)
So wait, if GetLocal always calls QuoteString, which always sprints at the end, how was the original code broken by lval being at an offset below the topmost sprintstack'ed offset?

/be
It doesn't *always* sprint. It only sprints in the DVG case, where it has to generate the name from the block object atom.
Comment on attachment 252684 [details] [diff] [review]
Better fix, I think

This is good, thanks -- but now there's no caller of GetLocal that passes JS_FALSE for retract, so please get rid of that by evaluating partially with it equal to true.

/be
Attached patch Once moreSplinter Review
Attachment #252684 - Attachment is obsolete: true
Attachment #252710 - Flags: review?(brendan)
Attachment #252684 - Flags: review?(brendan)
Comment on attachment 252710 [details] [diff] [review]
Once more

Thanks, r=me.

/be
Attachment #252710 - Flags: review?(brendan) → review+
Fix checked into trunk.
Status: ASSIGNED → RESOLVED
Closed: 18 years ago
Resolution: --- → FIXED
Flags: in-testsuite+
/cvsroot/mozilla/js/tests/js1_7/extensions/regress-366668-01.js,v  <--  regress-366668-01.js

/cvsroot/mozilla/js/tests/js1_7/extensions/regress-366668-02.js,v  <--  regress-366668-02.js
verified fixed 2007-02-17 1.9.0 windows/mac*/linux, note tests pass on 1.8.1 as well.
Status: RESOLVED → VERIFIED
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: