Closed Bug 772328 Opened 12 years ago Closed 12 years ago

function statements shouldn't shadow formals

Categories

(Core :: JavaScript Engine, defect)

defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla17

People

(Reporter: luke, Assigned: luke)

References

Details

(Whiteboard: [js:p2])

Attachments

(5 files, 6 obsolete files)

5.71 KB, patch
ejpbruel
: review+
Details | Diff | Splinter Review
32.10 KB, patch
ejpbruel
: review+
Details | Diff | Splinter Review
12.53 KB, patch
ejpbruel
: review+
Details | Diff | Splinter Review
47.12 KB, patch
Details | Diff | Splinter Review
1.34 KB, patch
ejpbruel
: review+
Details | Diff | Splinter Review
IIUC, this should return 42:

  function f(x) {
    function x() {}
    arguments[0] = 42;
    return x
  }

The reason is that Parser::functionDef calls addVariable if there is an existing formal binding.

Note: this offers a new opportunity for (undetected) shapes with duplicate ids.
(dmandelin needs [:dmandelin])
(In reply to Luke Wagner [:luke] from comment #1)
> (dmandelin needs [:dmandelin])

Heh, I never put one in because I figured my name chars were unique enough, so I was always waiting for someone to ask. :-)
> (dmandelin needs [:dmandelin])

Hear hear!  This has caught me lots of times;  I reflexively put a ':' in front of everybody's names.
Whiteboard: [js:p2]
In addition to being wrong, the function-shadowing-formals gets in the way of bug 775323.
Blocks: 775323
Attached patch simplify MakeDefIntoUse (obsolete) — Splinter Review
As explained in the comment added by this patch, MakeDefIntoUse is called when a function statement redeclares another function.  Currently we handle this by turning the former into a name that uses the latter.  We then hack the ParseNode's op to be JSOP_NOP which is a signal to the emitter not to do anything.  This causes trouble for a later patch.
Assignee: general → luke
Status: NEW → ASSIGNED
Attachment #645931 - Flags: review?(ejpbruel)
I'm tired of forgetting whether it's JOF_OPMODE or JOF_OPTYPE...
Attachment #645932 - Flags: review?(ejpbruel)
Attached patch fix and test (patch 3) (obsolete) — Splinter Review
This patch fixes the bug by making the op of the PNK_FUNC node tell whether the function is stored in an arg or local.  This patch also cleans up the logic in Parser::functionDef to be more understandable and conducive to the changes coming in bug 775323 (viz., avoiding the querying of bindings).
Attachment #645937 - Flags: review?(ejpbruel)
These patches assert and depend on several new frontend invariants and change some core frontend bits.  If you guys have time, do you suppose you could point the fuzzers at this patch and see if they find anything?
Attachment #645942 - Flags: feedback?(gary)
Attachment #645942 - Flags: feedback?(choller)
Comment on attachment 645942 [details] [diff] [review]
combined patch for fuzzing (applies to cset 7ad3878167c1)

function F(x, y) {}
function test(N) {
  var src = F.toSource(-1)+"\n";
  src = Array(N + 1).join(src);
  eval(src);
}
for (var i = 0; i != 10; ++i) {
  var time = test(1000 + i * 2000);
}


asserts with

Assertion failure: pnu->isUsed(), at js/src/frontend/Parser.cpp:878
Attachment #645942 - Flags: feedback?(choller) → feedback-
Comment on attachment 645942 [details] [diff] [review]
combined patch for fuzzing (applies to cset 7ad3878167c1)

I could spare a few mins for this - nothing severe immediately found on my side.
Attachment #645942 - Flags: feedback?(gary) → feedback+
Phew, thanks!  Here is the fixed patch.
Attachment #645931 - Attachment is obsolete: true
Attachment #645931 - Flags: review?(ejpbruel)
Attachment #645987 - Flags: review?(ejpbruel)
Attachment #645987 - Attachment description: simplify MakeDefIntoUse → simplify MakeDefIntoUse (patch 1)
Attachment #645932 - Attachment description: add IsArgOp and IsLocalOp → add IsArgOp and IsLocalOp (patch 2)
Attachment #645937 - Attachment description: fix and test → fix and test (patch 3)
If you have any more time (no rush), it'd be great to see if this patch holds up
Attachment #645942 - Attachment is obsolete: true
Attachment #645989 - Flags: feedback?(gary)
Attachment #645989 - Flags: feedback?(choller)
Comment on attachment 645989 [details] [diff] [review]
combined patch for fuzzing (applies to cset 462036803a34)

(function (call) { 
  function call() { } 
}).abstract.f++;


asserts with:

Assertion failure: *nextpc == JSOP_SETLOCAL || *nextpc == JSOP_SETALIASEDVAR, at js/src/jsopcode.cpp:4796
Attachment #645989 - Flags: feedback?(choller) → feedback-
*shakes fist at decompiler; hasn't Benjamin removed that yet?
Ah, this is just an assertion fix.  decoder, was this the only failure?  If this is fixed, do you think the patch passes fuzzing or did fuzzing not run long before finding this?
Attachment #645937 - Attachment is obsolete: true
Attachment #645937 - Flags: review?(ejpbruel)
Attachment #645989 - Attachment is obsolete: true
Attachment #645989 - Flags: feedback?(gary)
Attachment #646255 - Flags: feedback?(gary)
Attachment #646235 - Flags: review?(ejpbruel)
Comment on attachment 646255 [details] [diff] [review]
combined for fuzzing (applies to cset 462036803a34)

(function() {
  var x = (function() {})
  function x() {}
  function x() {}
})()

Assertion failure: pnu->isUsed(),
Attachment #646255 - Flags: feedback?(gary) → feedback-
Phew, painful.  Mutating parse node trees in place is not a good idea and fraught with peril.  Thanks Gary and Christian!
Attachment #645987 - Attachment is obsolete: true
Attachment #646255 - Attachment is obsolete: true
Attachment #645987 - Flags: review?(ejpbruel)
Attachment #646364 - Flags: review?(ejpbruel)
Comment on attachment 646369 [details] [diff] [review]
combined patch for fuzzing (applies to cset 462036803a34)

A night of fuzzing on my MBP did not throw up anything weird. \o/
Attachment #646369 - Flags: feedback?(gary) → feedback+
Phew, thanks again!
Attachment #645932 - Flags: review?(ejpbruel) → review+
A nice side-effect of the MakeDefIntoUse change is that we don't have this unbounded chain of definitions-converted-into-assignments which allows a nice simplification of ParseNode::resolve.
Attachment #649856 - Flags: review?(ejpbruel)
Comment on attachment 646235 [details] [diff] [review]
fix and test (patch 3)

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

This patch looks alright to me, but not 100% sure I didn't miss anything. Double checked some stuff with jorendorff over irc to make sure. Should be ok to r+, since you ran this stuff through the fuzzer.
Attachment #646235 - Flags: review?(ejpbruel) → review+
Comment on attachment 646364 [details] [diff] [review]
simplify MakeDefIntoUse (patch 1)

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

I got nothing
Attachment #646364 - Flags: review?(ejpbruel) → review+
Comment on attachment 649856 [details] [diff] [review]
simplify ParseNode::resolve (patch 4)

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

Looks good. Glad to see this being simplified. Thanks Luke!
Attachment #649856 - Flags: review?(ejpbruel) → review+
Comment on attachment 646235 [details] [diff] [review]
fix and test (patch 3)

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

::: js/src/frontend/BytecodeEmitter.cpp
@@ +1202,5 @@
>  static bool
>  BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
>  {
>      JS_ASSERT(pn->isKind(PNK_NAME));
> +    JS_ASSERT_IF(pn->isKind(PNK_FUNCTION), pn->isBound());

Can pn->isKind(PNK_FUNCTION) be true if the assert above this passes?
Good catch!  That is a left-over from earlier iterations of the patch.  I'll remove that in bug 775323.
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: