Last Comment Bug 730085 - Object.prototype.hasOwnProperty calls ToString on first argument before calling ToObject on this
: Object.prototype.hasOwnProperty calls ToString on first argument before calli...
Status: RESOLVED FIXED
[good first bug][mentor=Waldo][lang=c++]
:
Product: Core
Classification: Components
Component: JavaScript Engine (show other bugs)
: Trunk
: All All
: -- normal (vote)
: mozilla17
Assigned To: Saurabh Anand [:sawrubh]
:
:
Mentors:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2012-02-23 13:28 PST by André Bargull
Modified: 2012-08-18 16:18 PDT (History)
7 users (show)
See Also:
Crash Signature:
(edit)
QA Whiteboard:
Iteration: ---
Points: ---
Has Regression Range: ---
Has STR: ---


Attachments
Patch to fix the bug (2.79 KB, patch)
2012-04-19 06:44 PDT, phillip
no flags Details | Diff | Splinter Review
Patch v1 (3.87 KB, patch)
2012-08-17 12:04 PDT, Saurabh Anand [:sawrubh]
evilpies: feedback+
Details | Diff | Splinter Review
Patch v2 (4.05 KB, patch)
2012-08-17 22:24 PDT, Saurabh Anand [:sawrubh]
no flags Details | Diff | Splinter Review
Test v1 (791 bytes, patch)
2012-08-17 22:26 PDT, Saurabh Anand [:sawrubh]
evilpies: review+
Details | Diff | Splinter Review
Patch v3 (4.03 KB, patch)
2012-08-18 05:52 PDT, Saurabh Anand [:sawrubh]
evilpies: review+
Details | Diff | Splinter Review

Description André Bargull 2012-02-23 13:28:24 PST
User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Build ID: 20120215223356

Steps to reproduce:

Execute the following code in nightly Spidermonkey shell:
---
Object.prototype.hasOwnProperty.call(null, {toString: function(){ throw "ToString called" }})
---


Actual results:

js> Object.prototype.hasOwnProperty.call(null, {toString: function(){ throw "ToString called" }})
typein:1: TypeError: can't convert null to object


Expected results:

js> Object.prototype.hasOwnProperty.call(null, {toString: function(){ throw "ToString called" }})
uncaught exception: "ToString called"

See ECMAScript5.1, 15.2.4.5  Object.prototype.hasOwnProperty (V):
1.  Let P be ToString(V). 
2.  Let O be the result of calling ToObject passing the this value as the argument. 
[...]

So ToString() must be called before ToObject(), but this isn't the case in Spidermonkey otherwise an exception should have been reported.
Comment 1 Jeff Walden [:Waldo] (remove +bmo to email) 2012-02-23 13:42:47 PST
I could have sworn we wrote code specifically to implement this oddity correctly, but it seems not.  A fairly easy bug for anyone interested in getting into SpiderMonkey...
Comment 2 phillip 2012-04-19 06:44:32 PDT
Created attachment 616548 [details] [diff] [review]
Patch to fix the bug

The output is now as expected:

linkenhe@c166177:build_DBG.OBJ$ ./js
js> Object.prototype.hasOwnProperty.call(null, {toString: function(){ throw "ToString called" }})
uncaught exception: ToString called
js> 

Results of the test runs on my machine:

===================================================
===================================================
Tests after pull (that is:
Revision: 91915
Changeset: a9b543de6b67b00bb67d41981451bd5e9f04b4b6 [a9b543de6b67]
Author: Tim Taubert <tim.taubert@gmx.de>
Date: 19. April 2012 10:48:59 MESZ

merge m-c to fx-team; a=desktop-only
):
===================================================


linkenhe@c166177:src$ jit-test/jit_test.py build_DBG.OBJ/js
[4236|   2|   0|4238]    100% =======================================>|  285.1s
FAILURES:
    -m /Users/linkenhe/hg/spidermonkey/js/src/jit-test/tests/sunspider/check-date-format-tofte.js
    -m -n /Users/linkenhe/hg/spidermonkey/js/src/jit-test/tests/sunspider/check-date-format-tofte.js
TIMEOUTS:

linkenhe@c166177:src$ python2.7 tests/jstests.py build_DBG.OBJ/js --args="-m -n"
[3161|   6| 211] 100% ===============================================>|  578.8s8s
REGRESSIONS
    ecma/Date/15.9.5.35-1.js
    ecma_3/Date/15.9.5.5.js
    ecma_3/Date/15.9.5.6.js
    js1_5/extensions/toLocaleFormat-01.js
    js1_5/extensions/toLocaleFormat-02.js
    js1_5/Regress/regress-58116.js
FAIL

===================================================
===================================================
Tests with patch applied:
===================================================

linkenhe@c166177:src$ jit-test/jit_test.py build_DBG.OBJ/js
[4236|   2|   0|4238]    100% =======================================>|  282.2s
FAILURES:
    -m /Users/linkenhe/hg/spidermonkey/js/src/jit-test/tests/sunspider/check-date-format-tofte.js
    -m -n /Users/linkenhe/hg/spidermonkey/js/src/jit-test/tests/sunspider/check-date-format-tofte.js
TIMEOUTS:

linkenhe@c166177:src$ python2.7 tests/jstests.py build_DBG.OBJ/js --args="-m -n"
[3161|   6| 211] 100% ===============================================>|  571.7s7s
REGRESSIONS
    ecma/Date/15.9.5.35-1.js
    ecma_3/Date/15.9.5.5.js
    ecma_3/Date/15.9.5.6.js
    js1_5/extensions/toLocaleFormat-01.js
    js1_5/extensions/toLocaleFormat-02.js
    js1_5/Regress/regress-58116.js
FAIL
Comment 3 Jeff Walden [:Waldo] (remove +bmo to email) 2012-04-27 18:35:51 PDT
Comment on attachment 616548 [details] [diff] [review]
Patch to fix the bug

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

Sorry for the delay in getting to this, I've been kind of buried lately in other work and haven't been attending to reviews as promptly as I'd like.  :-\  Please do keep requesting review from me, tho, I'll be making a special effort to keep up with bugs I'm mentoring (and if that changes, I'll make sure to redirect appropriately).

::: js/src/jsobj.cpp
@@ +1264,5 @@
>  }
>  
> +static JSBool
> +obj_hasOwnProperty(JSContext *cx, unsigned argc, Value *vp)
> +{

This predated you, but lately we've been switching from using argc and vp directly to using CallArgs, like so:

  CallArgs args = CallArgsFromVp(argc, vp);
  // From here on use args.length() for argument length testing,
  // args[n] for the nth argument, args.thisv() for accessing the
  // passed-in |this| value, &args.rval() for accessing the
  // location in which to store the return value.

This form's a bit more readable than the current one, and in the long run we're going to do away with vp/argc entirely and just pass around CallArgs directly.

While you're touching this, mind changing obj_hasOwnProperty to use CallArgs?  For an example of how this works, see fun_bind in jsfun.cpp.

Also on the topic of style: we've taken to commenting the implementation to note each step taken, when it's taken, like /* Step 1. */, /* Steps 2-4. */, and so on.  (Sometimes the steps don't match up exactly to lines of code, but what correspondence there is, we find it helpful to note, even if it's out-of-order for efficiency or other reasons.)  And we prefix each method that corresponds to something in the standard with /* ES5 15.2.4.5. */ and such.  Mind applying that style while you're making changes here?  fun_bind is again a good example of how this works.

@@ +1270,5 @@
> +    // object (see line 2690) (I hope I'm right with that assumtation)
> +    
> +    // Fix: we have to convert the property name into a string first (bug 730085)
> +    
> +    // this code should trigger the toString call (I guess).

Yeah, we have a slightly different spelling of how we compute the names of properties -- this is the correct way to do it.

@@ +1290,5 @@
> +}
> +
> +JSBool
> +js_HasOwnPropertyHelper(JSContext *cx, LookupGenericOp lookup, unsigned argc,
> +                        Value *vp)

As it happens, js_HasOwnPropertyHelper really only has two callers: this one, and one in jsxml.cpp.  It looks to me like both cases can be changed so that inputs to the method that actually does the has-own-property computation (as opposed to exposing it to script calling some method) are the object, the LookupGenericOp to use to perform the lookup, and the jsid for the property.

Here's what I think we should do, then.  We should remove the ValueToId bits and the ToObject bits *both* from js_HasOwnPropertyHelper.  js_HasOwnPropertyHelper's signature should be changed to take (cx, obj, lookup, id, vp).  Then both callers can pick the order of operation they want -- this one to do ValueToId first and ToObject second, the XML one the other order.
Comment 4 phillip 2012-04-29 23:21:55 PDT
(In reply to Jeff Walden [:Waldo] (busy, try to prefer other reviewers if possible) from comment #3)
> Comment on attachment 616548 [details] [diff] [review]
> Patch to fix the bug
> 
> Review of attachment 616548 [details] [diff] [review]:
> -----------------------------------------------------------------
> 
> Sorry for the delay in getting to this, I've been kind of buried lately in
> other work and haven't been attending to reviews as promptly as I'd like. 
> :-\  Please do keep requesting review from me, tho, I'll be making a special
> effort to keep up with bugs I'm mentoring (and if that changes, I'll make
> sure to redirect appropriately).
Thank you very much for the feedback. I hope I find time in the next day to modify my path according o your suggestions.
Comment 5 Saurabh Anand [:sawrubh] 2012-08-17 12:04:46 PDT
Created attachment 652857 [details] [diff] [review]
Patch v1
Comment 6 AWAY Tom Schuster [:evilpie] 2012-08-17 12:25:17 PDT
Comment on attachment 652857 [details] [diff] [review]
Patch v1

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

Thank you for picking this up. I hope you are going to find something else to work on soon :)
This patch looks good to me. But you still need some test that would have have failed previously.

Something like:

>var calledToString = true;
>assertThrowsInstanceOf(function () { Object.prototype.hasOwnProperty.call(null, {toString: function() { calledToString = true; }}); }, TypeError);
>assertEq(calledToString, false);

::: js/src/jsobj.cpp
@@ +750,1 @@
>  {

Remove the "Proposed" above this line.

@@ +762,5 @@
> +    return js_HasOwnPropertyHelper(cx, obj->getOps()->lookupGeneric, args.rval(), obj, id);
> +}
> +
> +inline JSBool
> +js_HasOwnPropertyHelper(JSContext *cx, LookupGenericOp lookup, MutableHandleValue rval,

Personally I would make rval the last parameter.

@@ +765,5 @@
> +inline JSBool
> +js_HasOwnPropertyHelper(JSContext *cx, LookupGenericOp lookup, MutableHandleValue rval,
> +                        HandleObject obj, HandleId id)
> +{
> +    /* Step 3. */

Not the right place.

@@ +770,3 @@
>      RootedObject obj2(cx);
>      RootedShape prop(cx);
>      if (obj->isProxy()) {

Maybe "Non-standard code for proxies" or something like that?

@@ +777,4 @@
>          return true;
>      }
> +
> +    /* Step 4. */

As always we do things a little bit different, but this is more or less Step 3.

@@ +781,3 @@
>      if (!js_HasOwnProperty(cx, lookup, obj, id, &obj2, &prop))
> +        return false;
> +    rval.setBoolean(!!prop);

This is actually /* Step 4., 5. */

@@ +781,5 @@
>      if (!js_HasOwnProperty(cx, lookup, obj, id, &obj2, &prop))
> +        return false;
> +    rval.setBoolean(!!prop);
> +
> +    /* Step 5. */

"return true" just means the function did not fail (in the sense of throwing some exception). You can remove /* Step 5. */ here.

::: js/src/jsxml.cpp
@@ +5885,3 @@
>  static JSBool
>  xml_hasOwnProperty(JSContext *cx, unsigned argc, jsval *vp)
>  {

Thanks for bringing this code into 2012. I still hope it's going to be gone soon.
Comment 7 Saurabh Anand [:sawrubh] 2012-08-17 22:24:36 PDT
Created attachment 653020 [details] [diff] [review]
Patch v2
Comment 8 Saurabh Anand [:sawrubh] 2012-08-17 22:26:01 PDT
Created attachment 653021 [details] [diff] [review]
Test v1
Comment 9 Saurabh Anand [:sawrubh] 2012-08-18 01:05:33 PDT
https://tbpl.mozilla.org/?tree=Try&rev=865c2bd92d30
Comment 10 Saurabh Anand [:sawrubh] 2012-08-18 05:52:41 PDT
Created attachment 653048 [details] [diff] [review]
Patch v3

Removed the "inline" from the js_HasOwnPropertyHelper function and now the try run looks green on all the platforms.
Comment 11 Saurabh Anand [:sawrubh] 2012-08-18 07:17:48 PDT
The try run with the patch in comment 10 is :

https://tbpl.mozilla.org/?tree=Try&rev=aac95965eb86
Comment 12 AWAY Tom Schuster [:evilpie] 2012-08-18 07:54:51 PDT
Comment on attachment 653048 [details] [diff] [review]
Patch v3

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

Thanks for taking this!
Comment 13 AWAY Tom Schuster [:evilpie] 2012-08-18 12:11:04 PDT
http://hg.mozilla.org/integration/mozilla-inbound/rev/f1c9b2f9e8bd
Comment 14 Ryan VanderMeulen [:RyanVM] 2012-08-18 16:18:49 PDT
https://hg.mozilla.org/mozilla-central/rev/f1c9b2f9e8bd

Note You need to log in before you can comment on or make changes to this bug.