tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

side-effects-in-try.js (8462B)


      1 // -----------------------------------------------------------------------------
      2 // The tests in this file assert that any side effects that happened in try code
      3 // before an exception was thrown, will be known to the landing pad. It checks
      4 // local throws and throws from direct calls (of local and imported functions).
      5 // Side effects checked are changes to locals, and to globals.
      6 // -----------------------------------------------------------------------------
      7 
      8 load(libdir + "eqArrayHelper.js");
      9 
     10 
     11 function testSideEffectsOnLocals() {
     12  // Locals set before and after throwing instructions, either locally, or from
     13  // a direct wasm function call, for locals of all Wasm numtype and a local of
     14  // reftype (externref), and the thrown exception carrying a value from each
     15  // Wasm numtype and one of Wasm vectype (Simd128). Testing to see if the state
     16  // of the locals at the moment $exn is thrown, is known to the landing pad
     17  // when $exn is caught.
     18 
     19  let localThrow = "(throw $exn)";
     20 
     21  // The following is taken from calls.js
     22  // Some variables to be used in all tests.
     23  let typesJS = ["i32", "i64", "f32", "f64"];
     24  let types = typesJS.join(" ");
     25  let exnTypeDef = `(type $exnType (func (param ${types})))`;
     26  let correctLocalValues =
     27      `;; Correct local values
     28             (i32.const 2)
     29             (i64.const 3)
     30             (f32.const 4)
     31             (f64.const 13.37)`;
     32  let correctLocalValuesJS = [2, 3n, 4, 13.37];
     33 
     34  let wrongValues =
     35      `;; Wrong values.
     36             (i32.const 5)
     37             (i64.const 6)
     38             (f32.const 0.1)
     39             (f64.const 0.6437)`;
     40  let wrongValuesJS = [5, 6n, 0.1, 0.6437];
     41 
     42  // These variables are specific to the tests in this file.
     43  let throwValues =
     44      `;; Values to throw and catch.
     45             (i32.const 7)
     46             (i64.const 8)
     47             (f32.const 9)
     48             (f64.const 27.11)`;
     49  let thrownValuesJS = [7, 8n, 9, 27.11];
     50 
     51  let correctResultsJS = function(externref) {
     52    return [].concat(thrownValuesJS,
     53                     correctLocalValuesJS,
     54                     [externref, 1]);
     55  }
     56 
     57  // Testing also locals of Wasm vectype.
     58  // The following depend on whether simd is enabled or not. We write it like
     59  // this so we can run this test also when SIMD is not enabled.
     60  let wrongV128 = "";
     61  let correctV128 = "";
     62  let checkV128Value = "";
     63 
     64  if (wasmSimdEnabled()) {
     65    wrongV128 = `(v128.const i32x4 11 22 33 44)`;
     66    correctV128 = `(v128.const i32x4 55 66 77 88)`;
     67    checkV128Value =
     68      `       ${correctV128}
     69              (i32x4.eq)
     70              (i32x4.all_true)`;
     71    v128Type = " v128";
     72  } else {
     73    wrongV128 = "(i32.const 0)";
     74    correctV128 = "(i32.const 1)";
     75    v128Type = " i32";
     76  }
     77 
     78  let localTypes = types + " externref";
     79  let resultTypes = types + " " + localTypes;
     80 
     81  // The last i32 in the results is the v128 check.
     82  let testFuncTypeInline =
     83      `(param $argCorrectRef externref)
     84       (param $argWrongRef externref)
     85       (result ${resultTypes} i32)
     86       (local $localI32 i32)
     87       (local $localI64 i64)
     88       (local $localF32 f32)
     89       (local $localF64 f64)
     90       (local $localExternref externref)
     91       (local $localV128 ${v128Type})`;
     92 
     93  let localsSet =
     94      `;; Set locals.
     95             (local.set $localV128)
     96             (local.set $localExternref)
     97             (local.set $localF64)
     98             (local.set $localF32)
     99             (local.set $localI64)
    100             (local.set $localI32)`;
    101  let localsGet =
    102      `;; Get locals.
    103             (local.get $localI32)
    104             (local.get $localI64)
    105             (local.get $localF32)
    106             (local.get $localF64)
    107             (local.get $localExternref)
    108             (local.get $localV128)`;
    109 
    110  // The test module parts. ----------------------------------------------------
    111 
    112  let importsModule =
    113      `(module
    114         (type $exnType (func (param ${types})))
    115         (tag $exn (export "exn") (type $exnType))
    116         (func (export "throwif") (param $ifPredicate i32)
    117           (if (local.get $ifPredicate)
    118             (then
    119               ${throwValues}
    120               ${localThrow}))))`;
    121 
    122  let moduleHeader = `
    123       (module
    124         ${exnTypeDef}
    125         (import "m" "exn" (tag $exn (type $exnType)))
    126         (tag $emptyExn)
    127         (import "m" "throwif" (func $throwif (param $ifPredicate i32)))
    128         (func $wontThrow
    129           (throw $emptyExn))
    130         (func $localCallThrow
    131             ${throwValues}
    132             ${localThrow})
    133         (func (export "testFunc") ${testFuncTypeInline}
    134           try (result ${resultTypes} ${v128Type})
    135             ;; Locals not set.
    136             (i32.const 0) ;; Predicate for $throwif.
    137             (call $throwif)  ;; So this doesn't throw.
    138             ;; Set correct locals before throw to be caught.
    139             ${correctLocalValues}
    140             (local.get $argCorrectRef)
    141             ${correctV128}
    142             ${localsSet}
    143             ;; Next up should be $exn being thrown locally or via a call.`;
    144 
    145  let moduleRest = ` ;; The above throw to $exn should be caught here --------.
    146             ;; Set wrong locals after throw to be caught.              ;;    |
    147             ${wrongValues}                                             ;;    |
    148             (local.get $argWrongRef) ;; The wrong externref param.     ;;    |
    149             ${wrongV128}                                               ;;    |
    150             ${localsSet}                                               ;;    |
    151             (call $wontThrow)                                          ;;    |
    152             ${wrongValues}                                             ;;    |
    153             ${localsGet} ;; End of try code.                           ;;    |
    154           catch $emptyExn                                              ;;    |
    155             ${wrongValues}                                             ;;    |
    156             ${localsGet}                                               ;;    |
    157           catch $exn  ;; <---------------------------------------------------'
    158             ${localsGet}
    159           catch_all
    160             ${wrongValues}
    161             ${localsGet}
    162           end
    163           ;; Check if the local has the correct v128 value.
    164           ${checkV128Value}))`;
    165 
    166  let localThrowValues = `
    167             ${throwValues}
    168             (throw $exn)`;
    169  let directLocalCall = `
    170             (call $localCallThrow)`;
    171  let directImportCall = `
    172             (i32.const 1)
    173             (call $throwif)`;
    174 
    175  // Run test for side effects on locals before throwing an exception locally,
    176  // or from a direct call.
    177 
    178  let callInstructions = [localThrowValues, directLocalCall, directImportCall];
    179 
    180  for (let callThrow of callInstructions) {
    181    console.log("callThrow = " + callThrow); // Uncomment for debugging.
    182    moduleText = moduleHeader + callThrow + moduleRest;
    183    console.log("moduleText = " + moduleText); // Uncomment for debugging.
    184    assertEqArray(
    185      wasmEvalText(moduleText,
    186                   { m : wasmEvalText(importsModule).exports }
    187                  ).exports.testFunc("foo", "wrongFoo"),
    188      correctResultsJS("foo"));
    189  }
    190 }
    191 
    192 // Setting globals in try code, and testing to see if the changes are known to
    193 // the landing pad.
    194 function testGlobals() {
    195  let test = function (type, initialValue, resultValue, wrongValue, coercion) {
    196    let exports = wasmEvalText(
    197      `(module
    198         (tag (export "exn"))
    199         (func (export "throws")
    200           (throw 0)))`
    201    ).exports;
    202 
    203    assertEq(
    204      wasmEvalText(
    205        `(module
    206           (import "m" "exn" (tag $exn))
    207           (tag $notThrownExn)
    208           (import "m" "throws" (func $throws))
    209           (global (mut ${type}) (${type}.const ${initialValue}))
    210           (func (export "testFunc") (result ${type})
    211             try (result ${type})
    212               (global.set 0 (${type}.const ${resultValue}))
    213               (call $throws)
    214               (global.set 0 (${type}.const ${wrongValue}))
    215               (global.get 0)
    216             catch $notThrownExn
    217               (${type}.const ${wrongValue})
    218             catch $exn
    219               (global.get 0)
    220             end))`,
    221        { m: exports }
    222      ).exports.testFunc(), coercion(resultValue));
    223  };
    224 
    225  test("i32", 2, 7, 27, x => x);
    226  test("i64", 2n, 7n, 27n, x => x);
    227  test("f32", 0.3, 0.1, 0.6, Math.fround);
    228  test("f64", 13.37, 0.6437244242412325666666, 4, x => x);
    229 };
    230 
    231 // Run all tests.
    232 
    233 testSideEffectsOnLocals();
    234 testGlobals();