Bug 263954 - JSC should throw an exception when BigUint64Array copy value from Int32Array
Summary: JSC should throw an exception when BigUint64Array copy value from Int32Array
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: WebKit Nightly Build
Hardware: PC Linux
: P2 Normal
Assignee: Yijia Huang
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2023-10-31 01:05 PDT by EntryHi
Modified: 2023-11-02 12:47 PDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description EntryHi 2023-10-31 01:05:09 PDT
====================test.js=========
for (let v0 = 1; v0 < 100; v0++) {
  const v2 = [1000];
  const v4 = new BigUint64Array(v0);
  try {
    v4.set(v2);
    print(v4[0])
  } catch (e6) {print(e6)}
  Object.defineProperty(v2, 10, {writable: true,value: 10});
}

====================================

Run args: ./jsc -f test.js --useConcurrentJIT=0  --jitPolicyScale=0

JSC should throw an exception "TypeError: Invalid argument type in ToBigInt operation", but it didn't actually. This bug exists even when jitPolicyScale=1.

This bug may be related to runtime/JSGenericTypedArrayViewInlines.h setFromArrayLike

```
    if constexpr (TypedArrayStorageType != TypeBigInt64 || TypedArrayStorageType != TypeBigUint64) {
        if (JSArray* array = jsDynamicCast<JSArray*>(object); LIKELY(array && isJSArray(array))) {
            if (safeLength == length && (safeLength + objectOffset) <= array->length() && array->isIteratorProtocolFastAndNonObservable()) {
                IndexingType indexingType = array->indexingType() & IndexingShapeMask;
                if (indexingType == Int32Shape) {
                    copyFromInt32ShapeArray(offset, array, objectOffset, safeLength);
                    return true;
                }
                if (indexingType == DoubleShape) {
                    copyFromDoubleShapeArray(offset, array, objectOffset, safeLength);
                    return true;
                }
            }
        }
    }
```

In copyFromInt32ShapeArray does not assert even when typeValue == TypeBigInt64 becuase '||' in `ASSERT(Adaptor::typeValue != TypeBigInt64 || Adaptor::typeValue != TypeBigUint64)` , should this be a '&&'?


```
template<typename Adaptor>
void JSGenericTypedArrayView<Adaptor>::copyFromInt32ShapeArray(size_t offset, JSArray* array, size_t objectOffset, size_t length)
{
    ASSERT(canAccessRangeQuickly(offset, length));
    ASSERT((array->indexingType() & IndexingShapeMask) == Int32Shape);
    ASSERT(Adaptor::typeValue != TypeBigInt64 || Adaptor::typeValue != TypeBigUint64);
    ASSERT((length + objectOffset) <= array->length());
    ASSERT(array->isIteratorProtocolFastAndNonObservable());

    // If the destination is uint32_t or int32_t, we can use copyElements.
    // 1. int32_t -> uint32_t conversion does not change any bit representation. So we can simply copy them.
    // 2. Hole is represented as JSEmpty in Int32Shape, which lower 32bits is zero. And we expect 0 for undefined, thus this copying simply works.
    if constexpr (Adaptor::typeValue == TypeUint8 || Adaptor::typeValue == TypeInt8) {
        WTF::copyElements(bitwise_cast<uint8_t*>(typedVector() + offset), bitwise_cast<const uint64_t*>(array->butterfly()->contiguous().data() + objectOffset), length);
        return;
    }
    if constexpr (Adaptor::typeValue == TypeUint16 || Adaptor::typeValue == TypeInt16) {
        WTF::copyElements(bitwise_cast<uint16_t*>(typedVector() + offset), bitwise_cast<const uint64_t*>(array->butterfly()->contiguous().data() + objectOffset), length);
        return;
    }
    if constexpr (Adaptor::typeValue == TypeUint32 || Adaptor::typeValue == TypeInt32) {
        WTF::copyElements(bitwise_cast<uint32_t*>(typedVector() + offset), bitwise_cast<const uint64_t*>(array->butterfly()->contiguous().data() + objectOffset), length);
        return;
    }
    for (size_t i = 0; i < length; ++i) {
        JSValue value = array->butterfly()->contiguous().at(array, static_cast<unsigned>(i + objectOffset)).get();
        if (LIKELY(!!value))
            setIndexQuicklyToNativeValue(offset + i, Adaptor::toNativeFromInt32(value.asInt32()));
        else
            setIndexQuicklyToNativeValue(offset + i, Adaptor::toNativeFromUndefined());
    }
}
```

In copyFromInt32ShapeArray, when Adaptor::typeValue == TypeBigUint64, Int32 can not be convert to BigUint64 directly, it should throw an exception which is similar to `toNativeFromValue`.
Comment 1 Radar WebKit Bug Importer 2023-11-01 14:44:40 PDT
<rdar://problem/117816146>
Comment 2 Yijia Huang 2023-11-01 17:03:21 PDT
Pull request: https://github.com/WebKit/WebKit/pull/19868
Comment 3 EWS 2023-11-02 12:47:35 PDT
Committed 270133@main (0e5745978de8): <https://commits.webkit.org/270133@main>

Reviewed commits have been landed. Closing PR #19868 and removing active labels.