Changeset 195360 in webkit


Ignore:
Timestamp:
Jan 20, 2016 11:32:30 AM (8 years ago)
Author:
keith_miller@apple.com
Message:

[ES6] Fix various issues with TypedArrays.
https://bugs.webkit.org/show_bug.cgi?id=153245

Reviewed by Geoffrey Garen.

This patch fixes a couple of issues with TypedArrays:

1) We were not checking if a view had been neutered and throwing an error
if it had in the our TypedArray.prototype functions.

2) The TypedArray.prototype.set function had a couple of minor issues with
checking for the offset being negative.

3) The JSArrayBufferView class did not check if the backing store had
been neutered when computing the offset even though the view's vector
pointer had been set to NULL. This meant that under some conditions we
could, occasionally, return a garbage number as the offset. Now, we only
neuter views if the backing ArrayBuffer's view is actually transfered.

  • jsc.cpp:

(GlobalObject::finishCreation):
(functionNeuterTypedArray):

  • runtime/JSArrayBufferView.h:

(JSC::JSArrayBufferView::isNeutered):

  • runtime/JSArrayBufferViewInlines.h:

(JSC::JSArrayBufferView::byteOffset):

  • runtime/JSGenericTypedArrayViewPrototypeFunctions.h:

(JSC::genericTypedArrayViewProtoFuncSet):
(JSC::genericTypedArrayViewProtoFuncEntries):
(JSC::genericTypedArrayViewProtoFuncCopyWithin):
(JSC::genericTypedArrayViewProtoFuncFill):
(JSC::genericTypedArrayViewProtoFuncIndexOf):
(JSC::genericTypedArrayViewProtoFuncJoin):
(JSC::genericTypedArrayViewProtoFuncKeys):
(JSC::genericTypedArrayViewProtoFuncLastIndexOf):
(JSC::genericTypedArrayViewProtoFuncReverse):
(JSC::genericTypedArrayViewPrivateFuncSort):
(JSC::genericTypedArrayViewProtoFuncSlice):
(JSC::genericTypedArrayViewProtoFuncSubarray):
(JSC::typedArrayViewProtoFuncValues):

  • runtime/JSTypedArrayViewPrototype.cpp:

(JSC::typedArrayViewPrivateFuncLength):
(JSC::typedArrayViewPrivateFuncSort): Deleted.

  • tests/stress/typedarray-functions-with-neutered.js: Added.

(getGetter):
(unit):
(args.new.Int32Array):
(arrays.typedArrays.map):
(checkProtoFunc.throwsCorrectError):
(checkProtoFunc):
(test):

Location:
trunk/Source/JavaScriptCore
Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r195330 r195360  
     12016-01-19  Keith Miller  <keith_miller@apple.com>
     2
     3        [ES6] Fix various issues with TypedArrays.
     4        https://bugs.webkit.org/show_bug.cgi?id=153245
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        This patch fixes a couple of issues with TypedArrays:
     9
     10        1) We were not checking if a view had been neutered and throwing an error
     11        if it had in the our TypedArray.prototype functions.
     12
     13        2) The TypedArray.prototype.set function had a couple of minor issues with
     14        checking for the offset being negative.
     15
     16        3) The JSArrayBufferView class did not check if the backing store had
     17        been neutered when computing the offset even though the view's vector
     18        pointer had been set to NULL. This meant that under some conditions we
     19        could, occasionally, return a garbage number as the offset. Now, we only
     20        neuter views if the backing ArrayBuffer's view is actually transfered.
     21
     22        * jsc.cpp:
     23        (GlobalObject::finishCreation):
     24        (functionNeuterTypedArray):
     25        * runtime/JSArrayBufferView.h:
     26        (JSC::JSArrayBufferView::isNeutered):
     27        * runtime/JSArrayBufferViewInlines.h:
     28        (JSC::JSArrayBufferView::byteOffset):
     29        * runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
     30        (JSC::genericTypedArrayViewProtoFuncSet):
     31        (JSC::genericTypedArrayViewProtoFuncEntries):
     32        (JSC::genericTypedArrayViewProtoFuncCopyWithin):
     33        (JSC::genericTypedArrayViewProtoFuncFill):
     34        (JSC::genericTypedArrayViewProtoFuncIndexOf):
     35        (JSC::genericTypedArrayViewProtoFuncJoin):
     36        (JSC::genericTypedArrayViewProtoFuncKeys):
     37        (JSC::genericTypedArrayViewProtoFuncLastIndexOf):
     38        (JSC::genericTypedArrayViewProtoFuncReverse):
     39        (JSC::genericTypedArrayViewPrivateFuncSort):
     40        (JSC::genericTypedArrayViewProtoFuncSlice):
     41        (JSC::genericTypedArrayViewProtoFuncSubarray):
     42        (JSC::typedArrayViewProtoFuncValues):
     43        * runtime/JSTypedArrayViewPrototype.cpp:
     44        (JSC::typedArrayViewPrivateFuncLength):
     45        (JSC::typedArrayViewPrivateFuncSort): Deleted.
     46        * tests/stress/typedarray-functions-with-neutered.js: Added.
     47        (getGetter):
     48        (unit):
     49        (args.new.Int32Array):
     50        (arrays.typedArrays.map):
     51        (checkProtoFunc.throwsCorrectError):
     52        (checkProtoFunc):
     53        (test):
     54
    1552016-01-19  Andy VanWagoner  <thetalecrafter@gmail.com>
    256
  • trunk/Source/JavaScriptCore/runtime/ArrayBuffer.cpp

    r172129 r195360  
    4545    bool isNeuterable = !m_pinCount;
    4646
    47     if (isNeuterable)
    48         m_contents.transfer(result);
    49     else {
     47    if (!isNeuterable) {
    5048        m_contents.copyTo(result);
    5149        if (!result.m_data)
    5250            return false;
     51        return true;
    5352    }
    5453
     54    m_contents.transfer(result);
    5555    for (size_t i = numberOfIncomingReferences(); i--;) {
    5656        JSCell* cell = incomingReferenceAt(i);
  • trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h

    r191221 r195360  
    160160    ArrayBuffer* buffer();
    161161    PassRefPtr<ArrayBufferView> impl();
     162    bool isNeutered() { return hasArrayBuffer() && !vector(); }
    162163    void neuter();
    163164   
  • trunk/Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h

    r191221 r195360  
    6767    if (!hasArrayBuffer())
    6868        return 0;
    69    
     69
     70    ASSERT(!vector() == !buffer()->data());
     71
    7072    ptrdiff_t delta =
    7173        bitwise_cast<uint8_t*>(vector()) - static_cast<uint8_t*>(buffer()->data());
  • trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h

    r194310 r195360  
    4444namespace JSC {
    4545
     46static const char* typedArrayBufferHasBeenDetachedErrorMessage = "Underlying ArrayBuffer has been detached from the view";
     47
    4648inline unsigned argumentClampedIndexFromStartOrEnd(ExecState* exec, int argument, unsigned length, unsigned undefinedValue = 0)
    4749{
     
    6971    unsigned offset;
    7072    if (exec->argumentCount() >= 2) {
    71         offset = exec->uncheckedArgument(1).toUInt32(exec);
     73        double offsetNumber = exec->uncheckedArgument(1).toInteger(exec);
    7274        if (exec->hadException())
    7375            return JSValue::encode(jsUndefined());
     76        if (offsetNumber < 0)
     77            return throwVMRangeError(exec, "Offset should not be negative");
     78        offset = offsetNumber;
    7479    } else
    7580        offset = 0;
     81
     82    if (thisObject->isNeutered())
     83        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
    7684
    7785    JSObject* sourceArray = jsDynamicCast<JSObject*>(exec->uncheckedArgument(0));
     
    8088
    8189    unsigned length;
    82     if (isTypedView(sourceArray->classInfo()->typedArrayStorageType))
    83         length = jsDynamicCast<JSArrayBufferView*>(sourceArray)->length();
    84     else
     90    if (isTypedView(sourceArray->classInfo()->typedArrayStorageType)) {
     91        JSArrayBufferView* sourceView = jsCast<JSArrayBufferView*>(sourceArray);
     92        if (sourceView->isNeutered())
     93            return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
     94
     95        length = jsCast<JSArrayBufferView*>(sourceArray)->length();
     96    } else
    8597        length = sourceArray->get(exec, exec->vm().propertyNames->length).toUInt32(exec);
    8698
     
    97109    // 22.2.3.6
    98110    ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
     111    if (thisObject->isNeutered())
     112        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
    99113
    100114    return JSValue::encode(JSArrayIterator::create(exec, exec->callee()->globalObject()->arrayIteratorStructure(), ArrayIterateKeyValue, thisObject));
     
    106120    // 22.2.3.5
    107121    ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
     122    if (thisObject->isNeutered())
     123        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
    108124
    109125    if (exec->argumentCount() < 2)
     
    134150    // 22.2.3.8
    135151    ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
     152    if (thisObject->isNeutered())
     153        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
    136154
    137155    JSValue valueToInsert = exec->argument(0);
     
    157175    // 22.2.3.13
    158176    ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
     177    if (thisObject->isNeutered())
     178        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
    159179
    160180    if (!exec->argumentCount())
     
    182202EncodedJSValue JSC_HOST_CALL genericTypedArrayViewProtoFuncJoin(ExecState* exec)
    183203{
     204    ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
     205    if (thisObject->isNeutered())
     206        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
     207
    184208    // 22.2.3.14
    185209    auto joinWithSeparator = [&] (StringView separator) -> EncodedJSValue {
     
    215239    // 22.2.3.15
    216240    ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
     241    if (thisObject->isNeutered())
     242        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
    217243
    218244    return JSValue::encode(JSArrayIterator::create(exec, exec->callee()->globalObject()->arrayIteratorStructure(), ArrayIterateKey, thisObject));
     
    224250    // 22.2.3.16
    225251    ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
     252    if (thisObject->isNeutered())
     253        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
    226254
    227255    if (!exec->argumentCount())
     
    290318    // 22.2.3.21
    291319    ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
     320    if (thisObject->isNeutered())
     321        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
    292322
    293323    typename ViewClass::ElementType* array = thisObject->typedVector();
     
    302332    // 22.2.3.25
    303333    ViewClass* thisObject = jsCast<ViewClass*>(exec->argument(0));
     334    if (thisObject->isNeutered())
     335        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
    304336
    305337    thisObject->sort();
     
    315347
    316348    ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
     349    if (thisObject->isNeutered())
     350        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
    317351
    318352    if (!exec->argumentCount())
     
    350384
    351385    ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
     386    if (thisObject->isNeutered())
     387        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
    352388
    353389    if (!exec->argumentCount())
     
    386422    // 22.2.3.29
    387423    ViewClass* thisObject = jsCast<ViewClass*>(exec->thisValue());
     424    if (thisObject->isNeutered())
     425        return throwVMTypeError(exec, typedArrayBufferHasBeenDetachedErrorMessage);
    388426
    389427    return JSValue::encode(JSArrayIterator::create(exec, exec->callee()->globalObject()->arrayIteratorStructure(), ArrayIterateValue, thisObject));
  • trunk/Source/JavaScriptCore/runtime/JSTypedArrayViewPrototype.cpp

    r191864 r195360  
    6969    if (!thisObject)
    7070        return throwVMError(exec, createTypeError(exec, "Receiver should be a typed array view"));
     71    if (thisObject->isNeutered())
     72        return throwVMTypeError(exec, "Underlying ArrayBuffer has been detached from the view");
    7173
    7274    return JSValue::encode(jsNumber(thisObject->length()));
     
    7678{
    7779    JSValue thisValue = exec->argument(0);
    78     if (!thisValue.isObject())
    79         return throwVMError(exec, createTypeError(exec, "Receiver should be a typed array view but was not an object"));
    8080    CALL_GENERIC_TYPEDARRAY_PROTOTYPE_FUNCTION(genericTypedArrayViewPrivateFuncSort);
    8181}
Note: See TracChangeset for help on using the changeset viewer.