ClearScript icon indicating copy to clipboard operation
ClearScript copied to clipboard

Problem with ArrayBuffer bounds checking

Open raystubbs opened this issue 1 year ago • 4 comments

The following snippet breaks when contents is an empty array. Seems like bounds checking on sourceIndex and offset aren't correct for 0 length ArrayBuffer.

        public IArrayBuffer CreateJsBuffer(byte[] contents) {
            var buf = (IArrayBuffer)((ScriptObject)engine.Evaluate("ArrayBuffer")).Invoke(true, [contents.Length]);
            buf.WriteBytes(contents, 0, (ulong)contents.Length, 0);
            return buf;
        }
Specified argument was out of the range of valid values. (Parameter 'offset') Error: Specified argument was out of the range of valid values. (Parameter 'offset')

raystubbs avatar Jun 19 '24 20:06 raystubbs

Hi @raystubbs,

What behavior would you expect in this scenario? An index of zero is indeed out of range for a zero-length array.

Thanks!

ClearScriptLib avatar Jun 26 '24 21:06 ClearScriptLib

I'd expect it not to throw when copying 0 bytes with offset or sourceIndex as 0.

raystubbs avatar Jun 26 '24 21:06 raystubbs

I'd expect it not to throw when copying 0 bytes with offset or sourceIndex as 0.

So, if count is zero, the method should just return zero without checking the other arguments? While that would certainly be a simple change, we're not sure it would be more correct from an API perspective (unless there's precedent).

In any case, if that's the behavior you want, would it not be possible to check the count before invoking WriteBytes?

ClearScriptLib avatar Jun 28 '24 08:06 ClearScriptLib

Alright, I can't think of a particular example/precedent off the top of my head. But the fact that this behavior was surprising should probably be a hint in itself.

And we did change our code to do an explicit check. Just seems like it shouldn't be necessary.

Anyway thanks for the quick responses. If it isn't obvious to you that this isn't good, then probably no reason to change it. But may be worth noting the behavior in the docs.

raystubbs avatar Jun 28 '24 14:06 raystubbs

In terms of precedent, Array.Copy(xs, 0, ys, 0, 0); copies 0 values without complaint.

oconnor0 avatar Jan 27 '25 23:01 oconnor0

Hi @oconnor0,

In terms of precedent, Array.Copy(xs, 0, ys, 0, 0); copies 0 values without complaint.

Hmm, according to GetLowerBound and GetUpperBound, the index range of a zero-length .NET array is, paradoxically, [0, -1], which doesn't make sense from a strictly mathematical perspective. Nevertheless, an index of zero is considered valid even though it's beyond the upper bound in this particular case.

It therefore makes sense to allow zero-length data transfer to and from a zero-length array, but the array index must be zero. Specifying any other index should trigger an exception. That would match the Array.Copy behavior.

For consistency, the same rule should apply to zero-length JavaScript array buffers and typed arrays.

Thanks!

ClearScriptLib avatar Jan 28 '25 07:01 ClearScriptLib

ClearScript 7.5 fixed fast data transfer bounds checking for zero-length arrays and buffers

ClearScriptLib avatar Mar 08 '25 06:03 ClearScriptLib