Commit message: None
CVE: CVE-2018-9490
CWE: CWE-704
Vulnerability description: In CollectValuesOrEntriesImpl of elements.cc, there is possible remote code execution due to type confusion. This could lead to remote escalation of privilege with no additional execution privileges needed. User interaction is needed for exploitation. Product: Android. Versions: Android-7.0 Android-7.1.1 Android-7.1.2 Android-8.0 Android-8.1 Android-9.0 Android ID: A-111274046

Project: Android

 static void AddImpl(Handle<JSObject> object, uint32_t index,
 Handle<Object> value, PropertyAttributes attributes,
 uint32_t new_capacity) {
    UNREACHABLE();
 }

Project: Android

 static void AddImpl(Handle<JSObject> object, uint32_t index,
 Handle<Object> value, PropertyAttributes attributes,
 uint32_t new_capacity) {
    DCHECK_EQ(NONE, attributes);
 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
 Handle<FixedArrayBase> old_elements(
 FixedArrayBase::cast(parameter_map->get(1)));
 if (old_elements->IsSeededNumberDictionary() ||
 static_cast<uint32_t>(old_elements->length()) < new_capacity) {
 GrowCapacityAndConvertImpl(object, new_capacity);
 }
 FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
 FastHoleyObjectElementsAccessor::SetImpl(arguments, index, *value);
 }

Project: Android

MaybeHandle<Object> ArrayConstructInitializeElements(Handle<JSArray> array,
 Arguments* args) {
 if (args->length() == 0) {
 JSArray::Initialize(array, JSArray::kPreallocatedArrayElements);
 return array;

 } else if (args->length() == 1 && args->at(0)->IsNumber()) {
 uint32_t length;
 if (!args->at(0)->ToArrayLength(&length)) {
 return ThrowArrayLengthRangeError(array->GetIsolate());
 }

 if (length > 0 && length < JSArray::kInitialMaxFastElementArray) {
 ElementsKind elements_kind = array->GetElementsKind();
 JSArray::Initialize(array, length, length);

 if (!IsFastHoleyElementsKind(elements_kind)) {
        elements_kind = GetHoleyElementsKind(elements_kind);
 JSObject::TransitionElementsKind(array, elements_kind);
 }
 } else if (length == 0) {
 JSArray::Initialize(array, JSArray::kPreallocatedArrayElements);
 } else {
 JSArray::Initialize(array, 0);
 JSArray::SetLength(array, length);
 }
 return array;
 }

 Factory* factory = array->GetIsolate()->factory();

 int number_of_elements = args->length();
 JSObject::EnsureCanContainElements(
      array, args, 0, number_of_elements, ALLOW_CONVERTED_DOUBLE_ELEMENTS);

 ElementsKind elements_kind = array->GetElementsKind();
 Handle<FixedArrayBase> elms;
 if (IsFastDoubleElementsKind(elements_kind)) {
    elms = Handle<FixedArrayBase>::cast(
        factory->NewFixedDoubleArray(number_of_elements));
 } else {
    elms = Handle<FixedArrayBase>::cast(
        factory->NewFixedArrayWithHoles(number_of_elements));
 }

 switch (elements_kind) {
 case FAST_HOLEY_SMI_ELEMENTS:
 case FAST_SMI_ELEMENTS: {
 Handle<FixedArray> smi_elms = Handle<FixedArray>::cast(elms);
 for (int entry = 0; entry < number_of_elements; entry++) {
        smi_elms->set(entry, (*args)[entry], SKIP_WRITE_BARRIER);
 }
 break;
 }
 case FAST_HOLEY_ELEMENTS:
 case FAST_ELEMENTS: {
 DisallowHeapAllocation no_gc;
 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
 Handle<FixedArray> object_elms = Handle<FixedArray>::cast(elms);
 for (int entry = 0; entry < number_of_elements; entry++) {
        object_elms->set(entry, (*args)[entry], mode);
 }
 break;
 }
 case FAST_HOLEY_DOUBLE_ELEMENTS:
 case FAST_DOUBLE_ELEMENTS: {
 Handle<FixedDoubleArray> double_elms =
 Handle<FixedDoubleArray>::cast(elms);
 for (int entry = 0; entry < number_of_elements; entry++) {
        double_elms->set(entry, (*args)[entry]->Number());
 }
 break;
 }
 default:
      UNREACHABLE();
 break;
 }

  array->set_elements(*elms);
  array->set_length(Smi::FromInt(number_of_elements));
 return array;
}

Project: Android

 static void DeleteAtEnd(Handle<JSObject> obj,
 Handle<BackingStore> backing_store, uint32_t entry) {
 uint32_t length = static_cast<uint32_t>(backing_store->length());
 Isolate* isolate = obj->GetIsolate();
 for (; entry > 0; entry--) {
 if (!backing_store->is_the_hole(isolate, entry - 1)) break;
 }
 if (entry == 0) {
 FixedArray* empty = isolate->heap()->empty_fixed_array();
 if (obj->GetElementsKind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
 FixedArray::cast(obj->elements())->set(1, empty);
 } else {
        obj->set_elements(empty);
 }
 return;
 }

    isolate->heap()->RightTrimFixedArray(*backing_store, length - entry);
 }

Project: Android

 static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) {
 ElementsKind kind = KindTraits::Kind;
 if (IsFastPackedElementsKind(kind)) {
 JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind));
 }
 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
 JSObject::EnsureWritableFastElements(obj);
 }
 DeleteCommon(obj, entry, handle(obj->elements()));
 }

Project: Android

 static Handle<FixedArray> DirectCollectElementIndicesImpl(
 Isolate* isolate, Handle<JSObject> object,
 Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
 PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices,
 uint32_t insertion_index = 0) {
 uint32_t length = Subclass::GetMaxIndex(*object, *backing_store);
 for (uint32_t i = 0; i < length; i++) {
 if (Subclass::HasElementImpl(isolate, object, i, backing_store, filter)) {
 if (convert == GetKeysConversion::kConvertToString) {
 Handle<String> index_string = isolate->factory()->Uint32ToString(i);
 list->set(insertion_index, *index_string);
 } else {
 list->set(insertion_index, Smi::FromInt(i), SKIP_WRITE_BARRIER);
 }
        insertion_index++;
 }
 }
 *nof_indices = insertion_index;
 return list;
 }

Project: Android

 explicit FastPackedSmiElementsAccessor(const char* name)
 : FastSmiOrObjectElementsAccessor<
 FastPackedSmiElementsAccessor,
 ElementsKindTraits<FAST_SMI_ELEMENTS> >(name) {}

Project: Android

 static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) {
 uint32_t length = static_cast<uint32_t>(GetString(holder)->length());
 if (entry < length) {
 PropertyAttributes attributes =
 static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
 return PropertyDetails(kData, attributes, 0, PropertyCellType::kNoCell);
 }
 return BackingStoreAccessor::GetDetailsImpl(holder, entry - length);
 }

Project: Android

 static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
 Isolate* isolate = holder->GetIsolate();
 Handle<String> string(GetString(*holder), isolate);
 uint32_t length = static_cast<uint32_t>(string->length());
 if (entry < length) {
 return isolate->factory()->LookupSingleCharacterStringFromCode(
 String::Flatten(string)->Get(entry));
 }
 return BackingStoreAccessor::GetImpl(isolate, holder->elements(),
                                         entry - length);
 }

Project: Android

 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store,
 uint32_t entry) {
 return entry;
 }

Project: Android

 static bool HasAccessorsImpl(JSObject* holder,
 FixedArrayBase* backing_store) {
 return DictionaryElementsAccessor::HasAccessorsImpl(holder, backing_store);
 }

Project: Android

 static bool HasElementImpl(Isolate* isolate, Handle<JSObject> holder,
 uint32_t index,
 Handle<FixedArrayBase> backing_store,
 PropertyFilter filter = ALL_PROPERTIES) {
 return Subclass::GetEntryForIndexImpl(isolate, *holder, *backing_store,
                                          index, filter) != kMaxUInt32;
 }

Project: Android

 static bool HasParameterMapArg(FixedArray* parameter_map, uint32_t index) {
 uint32_t length = parameter_map->length() - 2;
 if (index >= length) return false;
 return !parameter_map->get(index + 2)->IsTheHole(
        parameter_map->GetIsolate());
 }

Project: Android

 static bool IsPackedImpl(Handle<JSObject> holder,
 Handle<FixedArrayBase> backing_store, uint32_t start,
 uint32_t end) {
 if (IsFastPackedElementsKind(kind())) return true;
 Isolate* isolate = backing_store->GetIsolate();
 for (uint32_t i = start; i < end; i++) {
 if (!Subclass::HasElementImpl(isolate, holder, i, backing_store,
                                    ALL_PROPERTIES)) {
 return false;
 }
 }
 return true;
 }

Project: Android

 static uint32_t NumberOfElementsImpl(JSObject* receiver,
 FixedArrayBase* backing_store) {
 return AccessorClass::GetCapacityImpl(receiver, backing_store);
 }

Project: Android

 explicit TypedElementsAccessor(const char* name)
 : ElementsAccessorBase<AccessorClass,
 ElementsKindTraits<Kind> >(name) {}