Bug 52768 - Construction of Uint8Array from JS Array (and possibly others) incorrectly clamps values
Summary: Construction of Uint8Array from JS Array (and possibly others) incorrectly cl...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebGL (show other bugs)
Version: 528+ (Nightly build)
Hardware: All All
: P2 Normal
Assignee: Kenneth Russell
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-01-19 16:50 PST by Kenneth Russell
Modified: 2011-02-17 15:13 PST (History)
3 users (show)

See Also:


Attachments
Patch (31.83 KB, patch)
2011-02-16 17:38 PST, Kenneth Russell
cmarrin: review+
kbr: commit-queue-
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Kenneth Russell 2011-01-19 16:50:00 PST
Tim Johansson from Opera has pointed out that in the WebGL test more/functions/drawElementsBadArgs.html in the Khronos repository, construction of Uint8Array (and possibly other types) taking a JS array is clamping values rather than performing modulo arithmetic. In other words, construction with an array containing the value 256 is resulting in a Uint8Array containing 255 rather than 0. It isn't clear yet whether this bug is in both the JSC and V8 bindings.
Comment 1 Kenneth Russell 2011-01-19 17:15:24 PST
The bug is in the common C++ code, specifically IntegralTypedArrayBase.h. It's explicitly clamping the incoming double value to the element type's minimum and maximum values, where it should be using casting behavior.
Comment 2 Zhenyao Mo 2011-01-24 15:57:12 PST
Also the conformance test array-unit-tests.html is failing due to 0.6 is mapped to 1 instead of 0.  According to Web IDL type mapping, floor(abs(x)) * sign(x) is the correct behavior.  Maybe it could be fixed in one patch as the code is in the same function.
Comment 3 Kenneth Russell 2011-01-24 16:16:37 PST
The rounding mode failure in array-unit-tests.html in Chromium is a different problem. That fix has been committed to V8 and we are waiting for it to be rolled into Chromium.
Comment 4 Chris Marrin 2011-01-24 17:40:26 PST
(In reply to comment #0)
> Tim Johansson from Opera has pointed out that in the WebGL test more/functions/drawElementsBadArgs.html in the Khronos repository, construction of Uint8Array (and possibly other types) taking a JS array is clamping values rather than performing modulo arithmetic. In other words, construction with an array containing the value 256 is resulting in a Uint8Array containing 255 rather than 0. It isn't clear yet whether this bug is in both the JSC and V8 bindings.

Looking at the typed array spec, it could be more clear about these conversions. There is one statement in the "omittable setter" part of section 5 that gives a link to the WebIDL spec. But I think it would be better call this out into its own section.

I've opened a spec bug about this: https://www.khronos.org/bugzilla/show_bug.cgi?id=420. It's in the WebGL area, which I suppose is an appropriate place for it for now.
Comment 5 Kenneth Russell 2011-02-16 17:31:56 PST
(In reply to comment #4)
> (In reply to comment #0)
> > Tim Johansson from Opera has pointed out that in the WebGL test more/functions/drawElementsBadArgs.html in the Khronos repository, construction of Uint8Array (and possibly other types) taking a JS array is clamping values rather than performing modulo arithmetic. In other words, construction with an array containing the value 256 is resulting in a Uint8Array containing 255 rather than 0. It isn't clear yet whether this bug is in both the JSC and V8 bindings.
> 
> Looking at the typed array spec, it could be more clear about these conversions. There is one statement in the "omittable setter" part of section 5 that gives a link to the WebIDL spec. But I think it would be better call this out into its own section.
> 
> I've opened a spec bug about this: https://www.khronos.org/bugzilla/show_bug.cgi?id=420. It's in the WebGL area, which I suppose is an appropriate place for it for now.

For the record, the spec bug has been fixed; the typed array spec is much more clear about rounding mode and type conversion behavior.
Comment 6 Kenneth Russell 2011-02-16 17:38:03 PST
Created attachment 82729 [details]
Patch
Comment 7 Chris Marrin 2011-02-17 10:53:20 PST
Comment on attachment 82729 [details]
Patch

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

Generally fine, one nit, and one question about the necessity of LargestIntType in the template. r=me, after settling those.

> Source/WebCore/ChangeLog:13
> +        required template parameter.

I don't understand the second parameter to IntegralTypedArrayBase. It's always a 64 bit int, which it would have to be to hold a any possible double. I don't think having it be a uint64 in some places is useful because a signed 64 bit number is plenty to hold all possible double values. I think JS requires numbers to be doubles so why not just eliminate it? Seems like unnecessary future-proofing

> Source/WebCore/bindings/js/JSArrayBufferViewHelper.h:137
> +        unsigned length = srcArray->get(exec, JSC::Identifier(exec, "length")).toUInt32(exec);

It would be more consistent to use uint32_t instead of unsigned here?
Comment 8 Kenneth Russell 2011-02-17 14:06:27 PST
(In reply to comment #7)
> (From update of attachment 82729 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=82729&action=review
> 
> Generally fine, one nit, and one question about the necessity of LargestIntType in the template. r=me, after settling those.
> 
> > Source/WebCore/ChangeLog:13
> > +        required template parameter.
> 
> I don't understand the second parameter to IntegralTypedArrayBase. It's always a 64 bit int, which it would have to be to hold a any possible double. I don't think having it be a uint64 in some places is useful because a signed 64 bit number is plenty to hold all possible double values. I think JS requires numbers to be doubles so why not just eliminate it? Seems like unnecessary future-proofing

I didn't experiment enough, but you're right; the intermediate cast can always be to int64_t, so the LargestIntType template parameter can be eliminated. This simplifies the patch.

> > Source/WebCore/bindings/js/JSArrayBufferViewHelper.h:137
> > +        unsigned length = srcArray->get(exec, JSC::Identifier(exec, "length")).toUInt32(exec);
> 
> It would be more consistent to use uint32_t instead of unsigned here?

OK, I'll make this change.
Comment 9 Kenneth Russell 2011-02-17 15:13:15 PST
Committed r78919: <http://trac.webkit.org/changeset/78919>