WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
Bug 164123
[JSC] JSON.stringify should handle Proxy which is non JSArray but isArray is true
https://bugs.webkit.org/show_bug.cgi?id=164123
Summary
[JSC] JSON.stringify should handle Proxy which is non JSArray but isArray is ...
Kamil Frankowicz
Reported
2016-10-28 06:02:19 PDT
Created
attachment 293147
[details]
POC to trigger SEGFAULT (jsc) Affected SVN revision: 208042 To reproduce the problem: ./jsc wekbit_string_builder.js ASAN Output: ASAN:DEADLYSIGNAL ================================================================= ==16295==ERROR: AddressSanitizer: SEGV on unknown address 0x6041000021a3 (pc 0x7fa5adf38ee4 bp 0x0000ffffffff sp 0x7ffd4d2f6790 T0) ==16295==The signal is caused by a READ memory access. #0 0x7fa5adf38ee3 in WTF::StringBuilder::operator[](unsigned int) const XYZ/webkit/Source/WTF/wtf/text/StringBuilder.h:247:20 #1 0x7fa5adf38ee3 in JSC::Stringifier::Holder::appendNextProperty(JSC::Stringifier&, WTF::StringBuilder&) XYZ/webkit/Source/JavaScriptCore/runtime/JSONObject.cpp:465 #2 0x7fa5adf35501 in JSC::Stringifier::appendStringifiedValue(WTF::StringBuilder&, JSC::JSValue, JSC::JSObject*, JSC::PropertyNameForFunctionCall const&) XYZ/webkit/Source/JavaScriptCore/runtime/JSONObject.cpp:384:37 #3 0x7fa5adf31deb in JSC::Stringifier::stringify(JSC::Handle<JSC::Unknown>) XYZ/webkit/Source/JavaScriptCore/runtime/JSONObject.cpp:262:9 #4 0x7fa5adf406c4 in JSC::JSONProtoFuncStringify(JSC::ExecState*) XYZ/webkit/Source/JavaScriptCore/runtime/JSONObject.cpp:786:57 #5 0x7fa565afe027 (<unknown module>) AddressSanitizer can not provide additional info. SUMMARY: AddressSanitizer: SEGV XYZ/webkit/Source/WTF/wtf/text/StringBuilder.h:247:20 in WTF::StringBuilder::operator[](unsigned int) const ==16295==ABORTING Regards, Kamil Frankowicz
Attachments
POC to trigger SEGFAULT (jsc)
(71 bytes, application/javascript)
2016-10-28 06:02 PDT
,
Kamil Frankowicz
no flags
Details
Patch
(9.29 KB, patch)
2016-10-29 22:02 PDT
,
Yusuke Suzuki
no flags
Details
Formatted Diff
Diff
Patch
(10.09 KB, patch)
2016-10-29 23:20 PDT
,
Yusuke Suzuki
mark.lam
: review+
Details
Formatted Diff
Diff
Show Obsolete
(1)
View All
Add attachment
proposed patch, testcase, etc.
Radar WebKit Bug Importer
Comment 1
2016-10-29 09:49:23 PDT
<
rdar://problem/29015948
>
Yusuke Suzuki
Comment 2
2016-10-29 20:18:34 PDT
More easy way is `JSON.parse(new Proxy([undefined], {}));`. investigating.
Yusuke Suzuki
Comment 3
2016-10-29 20:21:24 PDT
s/parse/stringify/
Yusuke Suzuki
Comment 4
2016-10-29 22:02:02 PDT
Created
attachment 293328
[details]
Patch
Mark Lam
Comment 5
2016-10-29 23:00:10 PDT
Comment on
attachment 293328
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=293328&action=review
> Source/JavaScriptCore/ChangeLog:11 > + When JSON.stringify encounter the value like undefined, which results depend > + on the context. If it is produced under the object property context, we ignore > + that property. On the other hand, if it is produced under the array element > + context, we produce "null".
Can you quote the relevant urls to the spec here?
> Source/JavaScriptCore/runtime/JSONObject.cpp:265 > + Holder root(Holder::RootHolder, vm, object);
Why can't you just use: Holder root(vm, m_exec, object);
> Source/JavaScriptCore/runtime/JSONObject.cpp:426 > + , m_isArray(JSC::isArray(exec, object))
m_isJSArray is uninitialized here. Is that intentional?
> Source/JavaScriptCore/runtime/JSONObject.cpp:440 > +inline Stringifier::Holder::Holder(RootHolderTag, VM& vm, JSObject* object) > + : m_object(vm, object) > + , m_isArray(false) > + , m_isJSArray(false) > , m_index(0) > #ifndef NDEBUG > , m_size(0)
Why do we need this version? Won't the Holder(VM& vm, ExecState* exec, JSObject* object) work just as well?
Yusuke Suzuki
Comment 6
2016-10-29 23:09:50 PDT
Comment on
attachment 293328
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=293328&action=review
Thanks!
>> Source/JavaScriptCore/ChangeLog:11 >> + context, we produce "null". > > Can you quote the relevant urls to the spec here?
Yup! I'll include it.
https://tc39.github.io/ecma262/#sec-serializejsonarray
we write "null". But
https://tc39.github.io/ecma262/#sec-serializejsonobject
, we skip the property in 8-b.
>> Source/JavaScriptCore/runtime/JSONObject.cpp:265 >> + Holder root(Holder::RootHolder, vm, object); > > Why can't you just use: > Holder root(vm, m_exec, object);
I don't think using it directly is good. It calls `isArray` for the given object and isArray() could raise exceptions for some objects. Of course, here, the exception never happens. But I would like to explicitly say that this Holder does not cause any observable behaviors. That's why I did not include ExecState* in this constructor.
>> Source/JavaScriptCore/runtime/JSONObject.cpp:426 >> + , m_isArray(JSC::isArray(exec, object)) > > m_isJSArray is uninitialized here. Is that intentional?
Yes, that is intentional. And this function is original one and it is not changed. This m_isJSArray will be initialized when we call appendNextProperty for this holder.
>> Source/JavaScriptCore/runtime/JSONObject.cpp:440 >> , m_size(0) > > Why do we need this version? Won't the Holder(VM& vm, ExecState* exec, JSObject* object) work just as well?
Yeah, it works. But I don't think it is good manner. And since we do not call appendNextProperty for this root Holder, some of the fields (m_isJSArray) remains uninitialized. I don't think it is good thing.
Yusuke Suzuki
Comment 7
2016-10-29 23:12:13 PDT
Notable example is, JSON.stringify({ value: undefined }) => "{}" JSON.stringify([undefined]) => "[null]"
Yusuke Suzuki
Comment 8
2016-10-29 23:16:00 PDT
Comment on
attachment 293328
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=293328&action=review
>>> Source/JavaScriptCore/runtime/JSONObject.cpp:426 >>> + , m_isArray(JSC::isArray(exec, object)) >> >> m_isJSArray is uninitialized here. Is that intentional? > > Yes, that is intentional. And this function is original one and it is not changed. > This m_isJSArray will be initialized when we call appendNextProperty for this holder.
But, I think initializing it is better. Since isJSArray() is not observable one, we can just call it here. I'll change this part.
Yusuke Suzuki
Comment 9
2016-10-29 23:20:53 PDT
Created
attachment 293335
[details]
Patch
Mark Lam
Comment 10
2016-10-30 00:03:40 PDT
Comment on
attachment 293335
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=293335&action=review
r=me
> Source/JavaScriptCore/ChangeLog:8 > + When JSON.stringify encounter the value like undefined, which results depend
/the value like undefined/the undefined value/ /which results depend/the result depends/
> Source/JavaScriptCore/ChangeLog:14 > + //
https://tc39.github.io/ecma262/#sec-serializejsonobject
I suggest adding "section 8.b" after the spec url above.
> Source/JavaScriptCore/ChangeLog:18 > + //
https://tc39.github.io/ecma262/#sec-serializejsonarray
I suggest adding "section 8.b" after the spec url above.
> JSTests/stress/json-stringify-with-non-jsarray-array.js:24 > +shouldBe(JSON.stringify(new Proxy([function() { }], {})), `[null]`);
Can you also add the test case for JSON.stringify(new Proxy({ value: undefined }, {}))?
Yusuke Suzuki
Comment 11
2016-10-30 00:49:05 PDT
Comment on
attachment 293335
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=293335&action=review
>> Source/JavaScriptCore/ChangeLog:8 >> + When JSON.stringify encounter the value like undefined, which results depend > > /the value like undefined/the undefined value/ > /which results depend/the result depends/
Oops, fixed.
>> Source/JavaScriptCore/ChangeLog:14 >> + //
https://tc39.github.io/ecma262/#sec-serializejsonobject
> > I suggest adding "section 8.b" after the spec url above.
Yeah, nice. Fixed.
>> Source/JavaScriptCore/ChangeLog:18 >> + //
https://tc39.github.io/ecma262/#sec-serializejsonarray
> > I suggest adding "section 8.b" after the spec url above.
Fixed.
>> JSTests/stress/json-stringify-with-non-jsarray-array.js:24 >> +shouldBe(JSON.stringify(new Proxy([function() { }], {})), `[null]`); > > Can you also add the test case for JSON.stringify(new Proxy({ value: undefined }, {}))?
Yup, added.
Yusuke Suzuki
Comment 12
2016-10-30 02:17:38 PDT
Committed
r208123
: <
http://trac.webkit.org/changeset/208123
>
Darin Adler
Comment 13
2016-10-30 15:22:49 PDT
Comment on
attachment 293335
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=293335&action=review
> Source/JavaScriptCore/runtime/JSONObject.cpp:431 > + , m_index(0) > +#ifndef NDEBUG > + , m_size(0) > +#endif
It would be better to initialize these in the class definition.
> Source/JavaScriptCore/runtime/JSONObject.cpp:441 > + , m_isArray(false) > + , m_isJSArray(false) > , m_index(0) > #ifndef NDEBUG > , m_size(0)
It would be better to initialize these in the class definition.
Yusuke Suzuki
Comment 14
2016-10-31 22:40:50 PDT
Comment on
attachment 293335
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=293335&action=review
Thanks, I'll create a follow-up patch.
>> Source/JavaScriptCore/runtime/JSONObject.cpp:431 >> +#endif > > It would be better to initialize these in the class definition.
Sounds nice. I'll move this function to the class definition. And use default initialization for some members (m_index for example).
>> Source/JavaScriptCore/runtime/JSONObject.cpp:441 >> , m_size(0) > > It would be better to initialize these in the class definition.
Ditto.
Kamil Frankowicz
Comment 15
2017-02-17 06:26:37 PST
This is CVE-2016-10222.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug