CVE-2020-1913 (JavaScript, published 2020-09-09T19:15Z)
Description: value: An Integer signedness error in the JavaScript Interpreter in Facebook Hermes prior to commit 2c7af7ec481ceffd0d14ce2d7c045e475fd71dc6 allows attackers to cause a denial of service attack or a potential RCE via crafted JavaScript. Note that this is only exploitable if the application using Hermes permits evaluation of untrusted JavaScript. Hence, most React Native applications are not affected.
Severity: MEDIUM (CVSS v3 base score: 8.1)
Weakness: CWE-681 \u2014 Incorrect Conversion between Numeric Types
When converting from one data type to another, such as long to integer, data can be omitted or translated in a way that produces unexpected values. If the resulting values are used in a sensitive context, then dangerous behaviors may occur.
Repository: https://github.com/facebook/hermes
Files changed:
lib/VM/Interpreter.cpp
test/Optimizer/switch_stmt.js
test/hermes/switch-regress1.js
Commit message: Fix backward branching in SwitchImm.

Summary:
`SwitchImm` can subtract from `ip`, but it was reading the offset
from a `uint32_t *` instead of `int32_t *`.
Change the type to the correct one.

Reviewed By: dulinriley

Differential Revision: D23114516

fbshipit-source-id: d4ddab94eb16dc1ce479590851eeb1ab428bd5d6


Vulnerable code:
            const uint32_t *loc =
                (const uint32_t *)tablestart + uintVal - ip->iSwitchImm.op4;

Fixed code:
            // Must be signed to account for backwards branching.
            const int32_t *loc =
                (const int32_t *)tablestart + uintVal - ip->iSwitchImm.op4;
/**
 * Copyright (c) Facebook, Inc. and its 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 -dump-ir %s | %FileCheck %s

function backwards_branch() {
  for (var i = 0; i < 4; i++) {
    switch (i) {
      case 0:
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
      case 6:
      case 7:
      case 8:
      case 9:
        break;
    }
    i = 2;
  }
}

// CHECK-LABEL: function backwards_branch() : undefined
// CHECK-NEXT: frame = []
// CHECK-NEXT: %BB0:
// CHECK-NEXT:   %0 = BranchInst %BB1
// CHECK-NEXT: %BB1:
// CHECK-NEXT:   %1 = PhiInst 0 : number, %BB0, 3 : number, %BB1
// CHECK-NEXT:   %2 = SwitchInst %1 : number, %BB1, 0 : number, %BB1, 1 : number, %BB1, 2 : number, %BB1, 3 : number, %BB1, 4 : number, %BB1, 5 : number, %BB1, 6 : number, %BB1, 7 : number, %BB1, 8 : number, %BB1, 9 : number, %BB1
// CHECK-NEXT: function_end
/**
 * Copyright (c) Facebook, Inc. and its 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 -O0 %s | %FileCheck --match-full-lines %s
// RUN: %hermes -O %s | %FileCheck --match-full-lines %s
// RUN: %hermes -O -emit-binary -out %t.hbc %s && %hermes %t.hbc | %FileCheck --match-full-lines %s

// Ensure that switch statements that are backwards branches work properly.

(function() {
  var j = 0;
  for (var i = 0; i < 4; i++) {
    ++j;
    if (j > 5) {
      return;
    }
    print(i);
    switch (i) {
      case 0:
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
      case 6:
      case 7:
      case 8:
      case 9:
        break;
    }
    i = 2;
  }
})();

// CHECK: 0
// CHECK: 3
// CHECK: 3
// CHECK: 3
// CHECK: 3