From 37195be7fc4d1d4b773f1cb466e2520dd8d6d030 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 13 Nov 2018 12:52:29 +0100 Subject: [Backport] Fix for CVE-2018-17478 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merged: [array] Ensure PrepareElementsForSort returns a legal value PrepareElementsForSort must return a number less than or equal the array length. No-Try: true No-Presubmit: true No-Treechecks: true Bug: chromium:897512, v8:7382 Change-Id: If5f9c4d052e623ab9f3300b8534603abbee859fa Reviewed-on: https://chromium-review.googlesource.com/c/1297958 Commit-Queue: Jakob Gruber Reviewed-by: Camillo Bruni Cr-Original-Commit-Position: refs/heads/master@{#56982} Reviewed-on: https://chromium-review.googlesource.com/c/1304354 Reviewed-by: Peter Marshall Cr-Commit-Position: refs/branch-heads/7.0@{#67} Cr-Branched-From: 6e2adae6f7f8e891cfd01f3280482b20590427a6-refs/heads/7.0.276@{#1} Cr-Branched-From: bc08a8624cbbea7a2d30071472bc73ad9544eadf-refs/heads/master@{#55424} Reviewed-by: Michael BrĂ¼ning Reviewed-by: Alexandru Croitor --- chromium/v8/src/runtime/runtime-array.cc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/chromium/v8/src/runtime/runtime-array.cc b/chromium/v8/src/runtime/runtime-array.cc index f07c842baec..5fc804d3a74 100644 --- a/chromium/v8/src/runtime/runtime-array.cc +++ b/chromium/v8/src/runtime/runtime-array.cc @@ -109,7 +109,15 @@ Object* PrepareSlowElementsForSort(Handle object, uint32_t limit) { new_dict->UpdateMaxNumberKey(max_key, object); JSObject::ValidateElements(*object); - return *isolate->factory()->NewNumberFromUint(result); + // TODO(jgruber, szuend, chromium:897512): This is a workaround to prevent + // returning a number greater than array.length to Array.p.sort, which could + // trigger OOB accesses. There is still a correctness bug here though in + // how we shift around undefineds and delete elements in the two blocks above. + // This needs to be fixed soon. + const uint32_t number_of_non_undefined_elements = std::min(limit, result); + + return *isolate->factory()->NewNumberFromUint( + number_of_non_undefined_elements); } // Collects all defined (non-hole) and non-undefined (array) elements at the @@ -123,6 +131,7 @@ Object* PrepareElementsForSort(Handle object, uint32_t limit) { } if (object->HasStringWrapperElements()) { int len = String::cast(Handle::cast(object)->value())->length(); + DCHECK_LE(len, limit); return Smi::FromInt(len); } @@ -241,6 +250,7 @@ Object* PrepareElementsForSort(Handle object, uint32_t limit) { } } + DCHECK_LE(result, limit); return *isolate->factory()->NewNumberFromUint(result); } -- cgit v1.2.3