RESOLVED FIXED 235271
[JSC] Fix Date functions' argument coercion
https://bugs.webkit.org/show_bug.cgi?id=235271
Summary [JSC] Fix Date functions' argument coercion
Yusuke Suzuki
Reported 2022-01-15 12:37:09 PST
[JSC] Fix Date functions' argument coercion
Attachments
Patch (14.69 KB, patch)
2022-01-15 12:39 PST, Yusuke Suzuki
ashvayka: review+
Yusuke Suzuki
Comment 1 2022-01-15 12:39:17 PST
Alexey Shvayka
Comment 2 2022-01-15 12:44:38 PST
Comment on attachment 449265 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=449265&action=review Super neat! > Source/JavaScriptCore/ChangeLog:9 > + arguments to Number since it has observable side effect. We might want to link spec PR: https://github.com/tc39/ecma262/pull/2136.
Yusuke Suzuki
Comment 3 2022-01-15 12:58:40 PST
(In reply to Alexey Shvayka from comment #2) > Comment on attachment 449265 [details] > Patch > > View in context: > https://bugs.webkit.org/attachment.cgi?id=449265&action=review > > Super neat! > > > Source/JavaScriptCore/ChangeLog:9 > > + arguments to Number since it has observable side effect. > > We might want to link spec PR: https://github.com/tc39/ecma262/pull/2136. Nice, done.
Yusuke Suzuki
Comment 4 2022-01-15 13:35:12 PST
Radar WebKit Bug Importer
Comment 5 2022-01-15 13:36:16 PST
Darin Adler
Comment 6 2022-01-16 13:53:49 PST
Comment on attachment 449265 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=449265&action=review Love patches like this one, beautifully done. > Source/JavaScriptCore/runtime/DatePrototype.cpp:113 > +static void applyToNumbersToTrashedArguments(JSGlobalObject* globalObject, CallFrame* callFrame, unsigned maxArgs) Terminology nitpicks: I would have called these "otherwise ignored" arguments, not "trashed" arguments. Also, should be "ToNumber" not "ToNumbers". > Source/JavaScriptCore/runtime/DatePrototype.cpp:118 > + unsigned numArgs = std::min<unsigned>(callFrame->argumentCount(), maxArgs); Not a problem in practice, but a subtle point about what <unsigned> means here is that that we *chop* argumentCount from size_t to unsigned, ignoring the high bits. So if we had a colossal argument count (which I suppose is impossible?) we could overflow and not apply toNumber to some of the arguments (which I suppose is relatively harmless). Not sure why size_t was the right type for argumentCount and yet unsigned is the right type for maxArgs, but this is the kind of thing that worries me when I see it, in principle. > Source/JavaScriptCore/runtime/DatePrototype.cpp:136 > + unsigned numArgs = std::min<unsigned>(callFrame->argumentCount(), maxArgs); Same thing here. > Source/JavaScriptCore/runtime/DatePrototype.cpp:185 > + unsigned numArgs = std::min<unsigned>(callFrame->argumentCount(), maxArgs); Here too. > Source/JavaScriptCore/runtime/DatePrototype.cpp:191 > + ok = (ok && std::isfinite(years)); Not sure the parentheses add clarity.
Yusuke Suzuki
Comment 7 2022-01-21 18:59:55 PST
Comment on attachment 449265 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=449265&action=review Thanks! >> Source/JavaScriptCore/runtime/DatePrototype.cpp:113 >> +static void applyToNumbersToTrashedArguments(JSGlobalObject* globalObject, CallFrame* callFrame, unsigned maxArgs) > > Terminology nitpicks: I would have called these "otherwise ignored" arguments, not "trashed" arguments. Also, should be "ToNumber" not "ToNumbers". Right, changed. >> Source/JavaScriptCore/runtime/DatePrototype.cpp:118 >> + unsigned numArgs = std::min<unsigned>(callFrame->argumentCount(), maxArgs); > > Not a problem in practice, but a subtle point about what <unsigned> means here is that that we *chop* argumentCount from size_t to unsigned, ignoring the high bits. So if we had a colossal argument count (which I suppose is impossible?) we could overflow and not apply toNumber to some of the arguments (which I suppose is relatively harmless). > > Not sure why size_t was the right type for argumentCount and yet unsigned is the right type for maxArgs, but this is the kind of thing that worries me when I see it, in principle. Actually, argumentCount() is stored in 32bit field, so it is unsigned (since it is never negative) :) >> Source/JavaScriptCore/runtime/DatePrototype.cpp:136 >> + unsigned numArgs = std::min<unsigned>(callFrame->argumentCount(), maxArgs); > > Same thing here. Ditto. >> Source/JavaScriptCore/runtime/DatePrototype.cpp:185 >> + unsigned numArgs = std::min<unsigned>(callFrame->argumentCount(), maxArgs); > > Here too. Ditto. >> Source/JavaScriptCore/runtime/DatePrototype.cpp:191 >> + ok = (ok && std::isfinite(years)); > > Not sure the parentheses add clarity. Removed.
Yusuke Suzuki
Comment 8 2022-01-21 19:03:12 PST
Darin Adler
Comment 9 2022-01-22 13:47:55 PST
Comment on attachment 449265 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=449265&action=review >>> Source/JavaScriptCore/runtime/DatePrototype.cpp:118 >>> + unsigned numArgs = std::min<unsigned>(callFrame->argumentCount(), maxArgs); >> >> Not a problem in practice, but a subtle point about what <unsigned> means here is that that we *chop* argumentCount from size_t to unsigned, ignoring the high bits. So if we had a colossal argument count (which I suppose is impossible?) we could overflow and not apply toNumber to some of the arguments (which I suppose is relatively harmless). >> >> Not sure why size_t was the right type for argumentCount and yet unsigned is the right type for maxArgs, but this is the kind of thing that worries me when I see it, in principle. > > Actually, argumentCount() is stored in 32bit field, so it is unsigned (since it is never negative) :) Maybe we should use unsigned or uint32_t instead of size_t for the return type for the argumentCount() function, then?
Yusuke Suzuki
Comment 10 2022-01-22 16:21:50 PST
Comment on attachment 449265 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=449265&action=review >>>> Source/JavaScriptCore/runtime/DatePrototype.cpp:118 >>>> + unsigned numArgs = std::min<unsigned>(callFrame->argumentCount(), maxArgs); >>> >>> Not a problem in practice, but a subtle point about what <unsigned> means here is that that we *chop* argumentCount from size_t to unsigned, ignoring the high bits. So if we had a colossal argument count (which I suppose is impossible?) we could overflow and not apply toNumber to some of the arguments (which I suppose is relatively harmless). >>> >>> Not sure why size_t was the right type for argumentCount and yet unsigned is the right type for maxArgs, but this is the kind of thing that worries me when I see it, in principle. >> >> Actually, argumentCount() is stored in 32bit field, so it is unsigned (since it is never negative) :) > > Maybe we should use unsigned or uint32_t instead of size_t for the return type for the argumentCount() function, then? Yeah, it should be. But we need to carefully review whether the existing code is effectively using size_t to handle some cases in that change :)
Note You need to log in before you can comment on or make changes to this bug.