RESOLVED FIXED 164007
JSGenericTypedArrayView::set() should check for exceptions.
https://bugs.webkit.org/show_bug.cgi?id=164007
Summary JSGenericTypedArrayView::set() should check for exceptions.
Mark Lam
Reported 2016-10-26 00:11:48 PDT
Patch coming.
Attachments
proposed patch. (4.38 KB, patch)
2016-10-26 00:36 PDT, Mark Lam
fpizlo: review+
Mark Lam
Comment 1 2016-10-26 00:20:24 PDT
Mark Lam
Comment 2 2016-10-26 00:36:50 PDT
Created attachment 292882 [details] proposed patch.
JF Bastien
Comment 3 2016-10-26 09:35:31 PDT
Comment on attachment 292882 [details] proposed patch. View in context: https://bugs.webkit.org/attachment.cgi?id=292882&action=review > JSTests/stress/typed-array-view-set-should-not-crash-on-exception.js:14 > + get: Date.prototype.getSeconds, Ew, this is horrible :-) > Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h:252 > length = std::min(length, other->length()); This is weird because other->length() is uint32_t and length is unsigned. Realistically unsigned is also uint32_t but if it weren't then it would potentially truncate (or if other->length()'s type were changed) which could lead to OOB things happening below (in the code you're changing, validating ranges of truncated things can get weird). It may be good to static_assert here that sizeof and sign are the same? > Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h:256 > + ASSERT(!scope.exception() == success); I don't understand what this assertion is checking. Success is the same as scope having raised an exception? Why? Exceptions can only occur if the range was borked?
Mark Lam
Comment 4 2016-10-26 09:43:17 PDT
Comment on attachment 292882 [details] proposed patch. View in context: https://bugs.webkit.org/attachment.cgi?id=292882&action=review >> Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h:252 >> length = std::min(length, other->length()); > > This is weird because other->length() is uint32_t and length is unsigned. Realistically unsigned is also uint32_t but if it weren't then it would potentially truncate (or if other->length()'s type were changed) which could lead to OOB things happening below (in the code you're changing, validating ranges of truncated things can get weird). It may be good to static_assert here that sizeof and sign are the same? This is pre-existing code. In my understanding, our codebase pretty much uses unsigned and uint32_t interchangeably. If that premise every becomes untrue, then all shorts of things will fail. Do we really want to start putting thee static_asserts every where? >> Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h:256 >> + ASSERT(!scope.exception() == success); > > I don't understand what this assertion is checking. Success is the same as scope having raised an exception? Why? Exceptions can only occur if the range was borked? Calling scope.exception(0 has side effects of satisfying a check for the exception scope verification process. This is how we do it (satisfy that check) when we want to check an alternate value (i.e. success in this case).
Mark Lam
Comment 5 2016-10-26 09:43:59 PDT
(In reply to comment #4) > Calling scope.exception(0 has ... /scope.exception(0/scope.exception()/
Geoffrey Garen
Comment 6 2016-10-26 10:01:38 PDT
Comment on attachment 292882 [details] proposed patch. View in context: https://bugs.webkit.org/attachment.cgi?id=292882&action=review >>> Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h:252 >>> length = std::min(length, other->length()); >> >> This is weird because other->length() is uint32_t and length is unsigned. Realistically unsigned is also uint32_t but if it weren't then it would potentially truncate (or if other->length()'s type were changed) which could lead to OOB things happening below (in the code you're changing, validating ranges of truncated things can get weird). It may be good to static_assert here that sizeof and sign are the same? > > This is pre-existing code. In my understanding, our codebase pretty much uses unsigned and uint32_t interchangeably. If that premise every becomes untrue, then all shorts of things will fail. Do we really want to start putting thee static_asserts every where? If there were a type mismatch between "length" and "other->length()", the call to min would fail to compile due to ambiguity, no? For example: scratch.cc: int main() { uint32_t x = 0; uint16_t y = 0; std::min(x, y); } clang++ -o scratch scratch.cc: scratch.cc:16:5: error: no matching function for call to 'min' std::min(x, y); ^~~~~~~~ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:2589:1: note: candidate template ignored: deduced conflicting types for parameter '_Tp' ('unsigned int' vs. 'unsigned short') min(const _Tp& __a, const _Tp& __b)
JF Bastien
Comment 7 2016-10-26 10:13:38 PDT
(In reply to comment #6) > Comment on attachment 292882 [details] > proposed patch. > > View in context: > https://bugs.webkit.org/attachment.cgi?id=292882&action=review > > >>> Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h:252 > >>> length = std::min(length, other->length()); > >> > >> This is weird because other->length() is uint32_t and length is unsigned. Realistically unsigned is also uint32_t but if it weren't then it would potentially truncate (or if other->length()'s type were changed) which could lead to OOB things happening below (in the code you're changing, validating ranges of truncated things can get weird). It may be good to static_assert here that sizeof and sign are the same? > > > > This is pre-existing code. In my understanding, our codebase pretty much uses unsigned and uint32_t interchangeably. If that premise every becomes untrue, then all shorts of things will fail. Do we really want to start putting thee static_asserts every where? > > If there were a type mismatch between "length" and "other->length()", the > call to min would fail to compile due to ambiguity, no? > > For example: > > scratch.cc: > > int main() > { > uint32_t x = 0; > uint16_t y = 0; > std::min(x, y); > } > > clang++ -o scratch scratch.cc: > > scratch.cc:16:5: error: no matching function for call to 'min' > std::min(x, y); > ^~~~~~~~ > /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault. > xctoolchain/usr/bin/../include/c++/v1/algorithm:2589:1: note: candidate > template ignored: deduced conflicting types for parameter '_Tp' > ('unsigned int' vs. 'unsigned short') > min(const _Tp& __a, const _Tp& __b) Oh yeah you're totally right! Ignore me :-)
Mark Lam
Comment 8 2016-10-26 12:27:35 PDT
Thanks for the review. Landed in r207906: <http://trac.webkit.org/r207906>.
Note You need to log in before you can comment on or make changes to this bug.