Bug 201910 - Array methods should throw TypeError upon attempting to modify a string
Summary: Array methods should throw TypeError upon attempting to modify a string
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: WebKit Local Build
Hardware: PC Linux
: P2 Normal
Assignee: Ross Kirsling
URL:
Keywords: InRadar
: 188789 189470 (view as bug list)
Depends on:
Blocks:
 
Reported: 2019-09-18 01:12 PDT by Yang Tian
Modified: 2020-06-07 06:39 PDT (History)
11 users (show)

See Also:


Attachments
testcase (121 bytes, text/javascript)
2019-09-18 01:12 PDT, Yang Tian
no flags Details
Patch (4.96 KB, patch)
2019-09-18 17:53 PDT, Ross Kirsling
no flags Details | Formatted Diff | Diff
Patch (6.82 KB, patch)
2019-09-18 22:21 PDT, Ross Kirsling
no flags Details | Formatted Diff | Diff
Patch for landing (6.83 KB, patch)
2019-09-23 16:26 PDT, Ross Kirsling
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Yang Tian 2019-09-18 01:12:54 PDT
Created attachment 379026 [details]
testcase

#Testcase:
1  var array = [ 0, 1, 2 ];
2  var str = "asdadc";
3  Array.prototype.push.apply(str, array);
4  print(str.length);
5  print(str);

#Command:
./webkit/WebKitBuild/Release/bin/jsc testcase.js

#Output:
6
asdadc

#Expected output:
Throw a TypeError in line3.

#Description:
When executing the above testcase, a TypeError should be thrown according to ECMAScript-262 standard. However, javascriptCore doesn't throw any exception but outputs "6" and "asdadc" while other JS engines such as V8, SpiderMonkey throw a TypeError. 

According to the output, I guess that JavaScriptCore neither executed Array.prototype.push() function normally nor thrown a TypeError. So I suspect that it's a bug of JavaScriptCore.

References: 
http://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.push
http://www.ecma-international.org/ecma-262/5.1/index.html#sec-15.4.4.7
Comment 1 Ross Kirsling 2019-09-18 11:11:08 PDT
Looks like this is a bug in JSC as well as XS, but there's no Test262 case enforcing it -- would you be willing to submit yours as a PR there?
https://github.com/tc39/test262

The specific issue is that Array#push calls the abstract operation Set(... , true) which makes failure to set into a TypeError.
(Thus `Array.prototype.push.call('abc', 1);` should throw even though `let x = 'abc'; x.length++;` does not.)
https://tc39.es/ecma262/#sec-array.prototype.push
https://tc39.es/ecma262/#sec-set-o-p-v-throw
Comment 2 Ross Kirsling 2019-09-18 17:53:25 PDT
Created attachment 379090 [details]
Patch
Comment 3 EWS Watchlist 2019-09-18 20:17:33 PDT
Comment on attachment 379090 [details]
Patch

Attachment 379090 [details] did not pass jsc-ews (mac):
Output: https://webkit-queues.webkit.org/results/13045120

New failing tests:
mozilla-tests.yaml/js1_6/Array/regress-304828.js.mozilla-llint
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.mini-mode
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.ftl-eager-no-cjit
mozilla-tests.yaml/js1_6/Array/regress-304828.js.mozilla
mozilla-tests.yaml/js1_6/Array/regress-304828.js.mozilla-dfg-eager-no-cjit-validate-phases
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.ftl-no-cjit-validate-sampling-profiler
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.ftl-no-cjit-b3o0
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.ftl-eager
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.no-cjit-collect-continuously
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.no-cjit-validate-phases
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.no-llint
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.ftl-no-cjit-no-inline-validate
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.ftl-no-cjit-no-put-stack-validate
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.ftl-no-cjit-small-pool
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.eager-jettison-no-cjit
mozilla-tests.yaml/js1_6/Array/regress-304828.js.mozilla-ftl-eager-no-cjit-validate-phases
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.ftl-eager-no-cjit-b3o1
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.no-ftl
mozilla-tests.yaml/js1_6/Array/regress-304828.js.mozilla-baseline
mozilla-tests.yaml/js1_6/Array/regress-304828.js.mozilla-no-ftl
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.dfg-eager-no-cjit-validate
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.dfg-eager
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.default
stress/phantom-insertion-live-range-should-agree-with-arguments-forwarding.js.bytecode-cache
Comment 4 Ross Kirsling 2019-09-18 21:52:46 PDT
Hmm, I think I will need Saam or Yusuke to tell me how phantom-insertion-live-range-should-agree-with-arguments-forwarding.js (from r250058) should be corrected, as `Object.__proto__ = []; Object.shift();` shouldn't be valid JavaScript (even though JSC is treating it as such before this patch).
Comment 5 Ross Kirsling 2019-09-18 22:21:55 PDT
Created attachment 379103 [details]
Patch
Comment 6 Saam Barati 2019-09-18 23:13:19 PDT
(In reply to Ross Kirsling from comment #4)
> Hmm, I think I will need Saam or Yusuke to tell me how
> phantom-insertion-live-range-should-agree-with-arguments-forwarding.js (from
> r250058) should be corrected, as `Object.__proto__ = []; Object.shift();`
> shouldn't be valid JavaScript (even though JSC is treating it as such before
> this patch).

I’d just make sure the test fails before my fix with this modification
Comment 7 Ross Kirsling 2019-09-18 23:25:25 PDT
(In reply to Saam Barati from comment #6)
> (In reply to Ross Kirsling from comment #4)
> > Hmm, I think I will need Saam or Yusuke to tell me how
> > phantom-insertion-live-range-should-agree-with-arguments-forwarding.js (from
> > r250058) should be corrected, as `Object.__proto__ = []; Object.shift();`
> > shouldn't be valid JavaScript (even though JSC is treating it as such before
> > this patch).
> 
> I’d just make sure the test fails before my fix with this modification

Confirmed!
Comment 8 Yang Tian 2019-09-22 18:44:57 PDT
(In reply to Ross Kirsling from comment #1)
> Looks like this is a bug in JSC as well as XS, but there's no Test262 case
> enforcing it -- would you be willing to submit yours as a PR there?
> https://github.com/tc39/test262
> 
> The specific issue is that Array#push calls the abstract operation Set(... ,
> true) which makes failure to set into a TypeError.
> (Thus `Array.prototype.push.call('abc', 1);` should throw even though `let x
> = 'abc'; x.length++;` does not.)
> https://tc39.es/ecma262/#sec-array.prototype.push
> https://tc39.es/ecma262/#sec-set-o-p-v-throw

I have no time to submit this to test262 now, but maybe later i will. And I want to confirm that this issue is a bug of JSC or not? thx.
Comment 9 Keith Miller 2019-09-23 16:07:39 PDT
Comment on attachment 379103 [details]
Patch

r=me.
Comment 10 Mark Lam 2019-09-23 16:10:49 PDT
Comment on attachment 379103 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=379103&action=review

> Source/JavaScriptCore/runtime/ArrayPrototype.cpp:187
> +    putLength(exec, vm, obj, jsNumber(value));

You should call scope.release() before the call to putLength() because we expect putLength() can throw.
Comment 11 Ross Kirsling 2019-09-23 16:26:05 PDT
Created attachment 379404 [details]
Patch for landing
Comment 12 Ross Kirsling 2019-09-23 16:26:26 PDT
(In reply to Mark Lam from comment #10)
> Comment on attachment 379103 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=379103&action=review
> 
> > Source/JavaScriptCore/runtime/ArrayPrototype.cpp:187
> > +    putLength(exec, vm, obj, jsNumber(value));
> 
> You should call scope.release() before the call to putLength() because we
> expect putLength() can throw.

Thanks! Addressed.
Comment 13 WebKit Commit Bot 2019-09-23 17:26:35 PDT
Comment on attachment 379404 [details]
Patch for landing

Clearing flags on attachment: 379404

Committed r250275: <https://trac.webkit.org/changeset/250275>
Comment 14 WebKit Commit Bot 2019-09-23 17:26:37 PDT
All reviewed patches have been landed.  Closing bug.
Comment 15 Radar WebKit Bug Importer 2019-09-23 17:27:16 PDT
<rdar://problem/55644328>
Comment 16 Alexey Shvayka 2020-06-07 06:38:22 PDT
*** Bug 188789 has been marked as a duplicate of this bug. ***
Comment 17 Alexey Shvayka 2020-06-07 06:39:52 PDT
*** Bug 189470 has been marked as a duplicate of this bug. ***