Changeset 175243 in webkit


Ignore:
Timestamp:
Oct 27, 2014 10:46:52 PM (9 years ago)
Author:
mark.lam@apple.com
Message:

Crash when attempting to perform array iteration on a non-array with numeric keys not initialized.
<https://webkit.org/b/137814>

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

The arrayIteratorNextThunkGenerator() thunk was not checking for the case where
the butterfly may be NULL. This was the source of the crash, and is now fixed.

In addition, it is also not checking for the case where a property named "length"
may have been set on the iterated object. The thunk only checks the butterfly's
publicLength for its iteration operation. Array objects will work fine with this
because it always updates its butterfly's publicLength when its length changes.
In the case of iterable non-Array objects, the "length" property will require a
look up outside of the scope of this thunk. The fix is simply to limit the fast
case checks in this thunk to Array objects.

  • jit/ThunkGenerators.cpp:

(JSC::arrayIteratorNextThunkGenerator):

LayoutTests:

  • js/array-length-shortening-expected.txt: Added.
  • js/array-length-shortening.html: Added.
  • js/for-of-crash-expected.txt: Added.
  • js/for-of-crash.html: Added.
  • js/script-tests/array-length-shortening.js: Added.

(testLengthShortening):
(denseInt32Elements):
(denseDoubleElements):
(denseObjectElements):
(holeyInt32Elements):
(holeyDoubleElements):
(holeyObjectElements):
(arrayStorageInt32Elements):
(arrayStorageDoubleElements):
(arrayStorageObjectElements):
(sparseInt32Elements):
(sparseDoubleElements):
(sparseObjectElements):

  • js/script-tests/for-of-crash.js: Added.

(foo):

Location:
trunk
Files:
6 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r175241 r175243  
     12014-10-27  Mark Lam  <mark.lam@apple.com>
     2
     3        Crash when attempting to perform array iteration on a non-array with numeric keys not initialized.
     4        <https://webkit.org/b/137814>
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * js/array-length-shortening-expected.txt: Added.
     9        * js/array-length-shortening.html: Added.
     10        * js/for-of-crash-expected.txt: Added.
     11        * js/for-of-crash.html: Added.
     12        * js/script-tests/array-length-shortening.js: Added.
     13        (testLengthShortening):
     14        (denseInt32Elements):
     15        (denseDoubleElements):
     16        (denseObjectElements):
     17        (holeyInt32Elements):
     18        (holeyDoubleElements):
     19        (holeyObjectElements):
     20        (arrayStorageInt32Elements):
     21        (arrayStorageDoubleElements):
     22        (arrayStorageObjectElements):
     23        (sparseInt32Elements):
     24        (sparseDoubleElements):
     25        (sparseObjectElements):
     26        * js/script-tests/for-of-crash.js: Added.
     27        (foo):
     28
    1292014-10-27  Chris Fleizach  <cfleizach@apple.com>
    230
  • trunk/Source/JavaScriptCore/ChangeLog

    r175240 r175243  
     12014-10-27  Mark Lam  <mark.lam@apple.com>
     2
     3        Crash when attempting to perform array iteration on a non-array with numeric keys not initialized.
     4        <https://webkit.org/b/137814>
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        The arrayIteratorNextThunkGenerator() thunk was not checking for the case where
     9        the butterfly may be NULL.  This was the source of the crash, and is now fixed.
     10
     11        In addition, it is also not checking for the case where a property named "length"
     12        may have been set on the iterated object.  The thunk only checks the butterfly's
     13        publicLength for its iteration operation.  Array objects will work fine with this
     14        because it always updates its butterfly's publicLength when its length changes.
     15        In the case of iterable non-Array objects, the "length" property will require a
     16        look up outside of the scope of this thunk.  The fix is simply to limit the fast
     17        case checks in this thunk to Array objects.
     18
     19        * jit/ThunkGenerators.cpp:
     20        (JSC::arrayIteratorNextThunkGenerator):
     21
    1222014-10-27  Mark Lam  <mark.lam@apple.com>
    223
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp

    r174996 r175243  
    11011101    jit.load8(Address(SpecializedThunkJIT::regT0, JSCell::indexingTypeOffset()), SpecializedThunkJIT::regT3);
    11021102    jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSObject::butterflyOffset()), SpecializedThunkJIT::regT2);
    1103    
    1104     jit.and32(TrustedImm32(IndexingShapeMask), SpecializedThunkJIT::regT3);
    1105 
     1103    Jump nullButterfly = jit.branchTestPtr(SpecializedThunkJIT::Zero, SpecializedThunkJIT::regT2);
     1104   
    11061105    Jump notDone = jit.branch32(SpecializedThunkJIT::Below, SpecializedThunkJIT::regT1, Address(SpecializedThunkJIT::regT2, Butterfly::offsetOfPublicLength()));
     1106
     1107    nullButterfly.link(&jit);
     1108
    11071109    // Return the termination signal to indicate that we've finished
    11081110    jit.move(TrustedImmPtr(vm->iterationTerminator.get()), SpecializedThunkJIT::regT0);
     
    11231125   
    11241126    // So now we perform inline loads for int32, value/undecided, and double storage
    1125     Jump undecidedStorage = jit.branch32(SpecializedThunkJIT::Equal, SpecializedThunkJIT::regT3, TrustedImm32(UndecidedShape));
    1126     Jump notContiguousStorage = jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(ContiguousShape));
     1127    Jump undecidedStorage = jit.branch32(SpecializedThunkJIT::Equal, SpecializedThunkJIT::regT3, TrustedImm32(ArrayWithUndecided));
     1128    Jump notContiguousStorage = jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(ArrayWithContiguous));
    11271129   
    11281130    undecidedStorage.link(&jit);
     
    11521154    notContiguousStorage.link(&jit);
    11531155   
    1154     Jump notInt32Storage = jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(Int32Shape));
     1156    Jump notInt32Storage = jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(ArrayWithInt32));
    11551157    jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSObject::butterflyOffset()), SpecializedThunkJIT::regT2);
    11561158    jit.load32(BaseIndex(SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT1, SpecializedThunkJIT::TimesEight, JSValue::offsetOfPayload()), SpecializedThunkJIT::regT0);
     
    11591161    notInt32Storage.link(&jit);
    11601162   
    1161     jit.appendFailure(jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(DoubleShape)));
     1163    jit.appendFailure(jit.branch32(SpecializedThunkJIT::NotEqual, SpecializedThunkJIT::regT3, TrustedImm32(ArrayWithDouble)));
    11621164    jit.loadPtr(Address(SpecializedThunkJIT::regT0, JSObject::butterflyOffset()), SpecializedThunkJIT::regT2);
    11631165    jit.loadDouble(BaseIndex(SpecializedThunkJIT::regT2, SpecializedThunkJIT::regT1, SpecializedThunkJIT::TimesEight), SpecializedThunkJIT::fpRegT0);
Note: See TracChangeset for help on using the changeset viewer.