CVE-2023-24833 (published 2023-05-18T22:15Z)

A use-after-free in BigIntPrimitive addition in Hermes prior to commit a6dcafe6ded8e61658b40f5699878cd19a481f80 could have been used by an attacker to leak raw data from Hermes VM’s heap. Note that this is only exploitable in cases where Hermes is used to execute untrusted JavaScript. Hence, most React Native applications are not affected.

CVSS v3 base score: 7.5, HIGH (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)

Weakness information:
cwe_id: CWE-416
cwe_name: Use After Free
description: The product reuses or references memory after it has been freed. At some point afterward, the memory may be allocated again and saved in another pointer, while the original pointer references a location somewhere within the new allocation. Any operations using the original pointer are no longer valid because the memory "belongs" to the code that operates on the new pointer.
extended_description: 
             
             
             
			 
             
             
         
         

Fix information:
repo_url: https://github.com/facebook/hermes
commit_details: repo_url: https://github.com/facebook/hermes
author: Facebook Community Bot
author_date: 2023-02-02 15:07:13-05:00
msg: Re-sync with internal repository (#908)

Fixes for CVE-2023-23556, and CVE-2023-24833.

Co-authored-by: Facebook Community Bot <6422482+facebook-github-bot@users.noreply.github.com>
repository: repo_url: https://github.com/facebook/hermes
repo_name: facebook/hermes
description: A JavaScript engine optimized for running React Native.
repo_language: C++
owner: facebook
file_changes: filename: BigIntSupport.cpp
change_type: ModificationType.MODIFY
diff: @@ -192,7 +192,11 @@ double toDouble(ImmutableBigIntRef src) {
   const uint32_t numBits = src.numDigits * BigIntDigitSizeInBits;
   llvh::APInt tmp(numBits, llvh::makeArrayRef(src.digits, src.numDigits));
   constexpr bool kSigned = true;
-  return tmp.roundToDouble(kSigned);
+  double val = tmp.roundToDouble(kSigned);
+  // TODO(T142034196): APInt::roundToDouble doesn't implement proper conversion
+  // when the number has more than 2 digits; we need to implement this
+  // conversion.
+  return std::isnan(val) ? std::numeric_limits<double>::quiet_NaN() : val;
 }
 
 namespace {

programming_language: C++
filename: Array.cpp
change_type: ModificationType.MODIFY
diff: @@ -1093,10 +1093,6 @@ class StandardSortModel : public SortModel {
     JSObject::getComputedPrimitiveDescriptor(
         obj_, runtime_, aHandle_, aDescObjHandle_, aTmpNameStorage_, aDesc);
 
-    ComputedPropertyDescriptor bDesc;
-    JSObject::getComputedPrimitiveDescriptor(
-        obj_, runtime_, bHandle_, bDescObjHandle_, bTmpNameStorage_, bDesc);
-
     if (aDescObjHandle_) {
       if (LLVM_LIKELY(!aDesc.flags.proxyObject)) {
         auto res = JSObject::getComputedPropertyValue_RJS(
@@ -1135,6 +1131,11 @@ class StandardSortModel : public SortModel {
         }
       }
     }
+
+    ComputedPropertyDescriptor bDesc;
+    JSObject::getComputedPrimitiveDescriptor(
+        obj_, runtime_, bHandle_, bDescObjHandle_, bTmpNameStorage_, bDesc);
+
     if (bDescObjHandle_) {
       if (LLVM_LIKELY(!bDesc.flags.proxyObject)) {
         auto res = JSObject::getComputedPropertyValue_RJS(

programming_language: C++
filename: Operations.cpp
change_type: ModificationType.MODIFY
diff: @@ -1272,8 +1272,8 @@ addOp_RJS(Runtime &runtime, Handle<> xHandle, Handle<> yHandle) {
 
   return BigIntPrimitive::add(
       runtime,
-      runtime.makeHandle(resX->getBigInt()),
-      runtime.makeHandle(resY->getBigInt()));
+      runtime.makeHandle(xPrim->getBigInt()),
+      runtime.makeHandle(yPrim->getBigInt()));
 }
 
 static const size_t MIN_RADIX = 2;

programming_language: C++
filename: regress-bigint-add-gc.js
change_type: ModificationType.ADD
diff: @@ -0,0 +1,21 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// RUN: %hermes -non-strict -O %s | %FileCheck %s
+// RUN: %hermes -non-strict -O0 %s | %FileCheck %s
+
+const obj = {
+    toString: () => {
+        gc();
+        return 0n;
+    }
+};
+// trigger after obj.toString called and before addOp complete
+let trigger_point = 1n + obj;
+print(trigger_point);
+
+// CHECK: 1

programming_language: C++
filename: regress-bigint-to-double-nan.js
change_type: ModificationType.ADD
diff: @@ -0,0 +1,13 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// RUN: %hermes -non-strict -O %s | %FileCheck %s
+// RUN: %hermes -non-strict -O0 %s | %FileCheck %s
+
+// TODO: fix BigInt to number conversion (it should never result in NaN).
+print(Number(0xffffffffffffffffffffffffffffffffn));
+// CHECK: NaN

programming_language: Batchfile
filename: regress-invalidated-descriptor-std-sort-model-swap.js
change_type: ModificationType.ADD
diff: @@ -0,0 +1,20 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+// RUN: %hermes -O %s
+
+var a = [0,1]
+a.sort(function(x,y){
+  a.__defineGetter__(1, function(){
+    delete a[0];
+    return 1;
+  });
+  a.__defineGetter__(0, function(){
+    return 1;
+  });
+  return -1;
+})

programming_language: JavaScript