tor-browser

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

private-methods-eval-in-frame.js (4586B)


      1 load(libdir + 'evalInFrame.js');
      2 
      3 class B {
      4  #priv() {
      5    return 12;
      6  }
      7 
      8  #privF = () => { return 12; }
      9 
     10  callPriv() {
     11    return this.#priv();
     12  }
     13 
     14  callPrivF() {
     15    return this.#privF();
     16  }
     17 
     18  #val = 'constructed';
     19  set #x(x) {
     20    this.#val = x + ' haha';
     21  }
     22  get #x() {
     23    return this.#val;
     24  }
     25 
     26  ef(str) {
     27    return evalInFrame(0, str);
     28  }
     29 
     30  layerEf(str) {
     31    // Nested functions here result in computeEffectiveScope traversing
     32    // more than one environment, necessitating more hops.
     33    function tester(o) {
     34      let a = 10;
     35      function interior(o) {
     36        let b = a;
     37        return evalInFrame(0, str.replace("this", "o"));
     38      };
     39      return interior(o);
     40    }
     41    return tester(this);
     42  }
     43 
     44  moreLayerEf(str) {
     45    // Nested functions here result in computeEffectiveScope traversing
     46    // more than one environment, necessitating more hops.
     47    function tester(o) {
     48      let a = 0;
     49      function interior(o) {
     50        let b = a;
     51        return (() => {
     52          let k = o;
     53          let replace = str.replace("this", "k");
     54          print(replace);
     55          return evalInFrame(b, replace);
     56        })();
     57      };
     58      return interior(o);
     59    }
     60    return tester(this);
     61  }
     62 
     63  callFunc(f) {
     64    return f();
     65  }
     66 
     67  static #smethod() {
     68    return 14;
     69  }
     70 
     71  static #unusedmethod() {
     72    return 19;
     73  }
     74 
     75  static get #unusedgetter() {
     76    return 10;
     77  }
     78 
     79  static setter = undefined;
     80  static set #unusedsetter(x) { this.setter = x }
     81 
     82 
     83  static f() {
     84    return this.#smethod();
     85  }
     86 
     87  static seval(str) {
     88    return eval(str);
     89  }
     90 
     91  static sef(str) {
     92    return evalInFrame(0, str);
     93  }
     94 
     95 
     96  static sLayerEf(str) {
     97    // Nested functions here result in computeEffectiveScope traversing
     98    // more than one environment, necessitating more hops.
     99    function tester(o) {
    100      let a = 10;
    101      function interior(o) {
    102        if (a == 10) {
    103          let b = 10 - a;
    104          return evalInFrame(b, str.replace("this", "o"));
    105        }
    106      };
    107      return interior(o);
    108    }
    109    return tester(this);
    110  }
    111 
    112 
    113 }
    114 
    115 var b = new B();
    116 
    117 assertEq(b.ef("this.callPriv()"), 12);
    118 assertEq(b.ef("this.callPrivF()"), 12);
    119 
    120 // Private fields don't need brand checking and should succeed.
    121 assertEq(b.ef("this.#val"), 'constructed')
    122 
    123 // PrivF is a field, not a method, and so isn't brand checked like a method.
    124 assertEq(b.ef(`this.callFunc(() => { return this.#privF() })`), 12);
    125 assertEq(b.ef(`this.#privF()`), 12);
    126 
    127 // Accesors are stored like fields, and so successfully execute, as they don't
    128 // need brand checking.
    129 assertEq(b.ef(`this.#x = 'Bye'; this.#x`), 'Bye haha');
    130 assertEq(b.ef(`var x = () => { this.#x = 'Hi'; return this.#x}; x()`), 'Hi haha');
    131 
    132 
    133 // // Private methods require very special brand checking.
    134 assertEq(b.ef(`this.#priv()`), 12);
    135 assertEq(b.ef(`let hello;
    136 let f = () => {
    137  hello = this.#priv();
    138  assertEq(hello, 12);
    139 };
    140 f();
    141 hello`), 12);
    142 assertEq(b.layerEf(`this.#priv()`), 12);
    143 assertEq(b.moreLayerEf(`this.#priv()`), 12);
    144 
    145 if ('dis' in this) {
    146  // Ensure disassembly of GetAliasedDebugVar wroks.
    147  assertEq(b.ef(`dis(); this.#priv()`), 12);
    148 }
    149 
    150 assertEq(b.ef(`var x = () => { return this.#priv(); }; x()`), 12);
    151 assertEq(b.ef(`function x(o) { function y(o) { return o.#priv(); }; return y(o); } x(this)`), 12);
    152 
    153 assertEq(B.f(), 14);
    154 assertEq(B.sef(`this.#smethod()`), 14);
    155 assertEq(B.sLayerEf(`this.#smethod()`), 14);
    156 assertEq(B.sef("this.#unusedmethod()"), 19);
    157 assertEq(B.sef("this.#unusedgetter"), 10);
    158 
    159 
    160 B.sef("this.#unusedsetter = 13");
    161 assertEq(B.setter, 13);
    162 
    163 // Test case variant from Arai.
    164 class C {
    165  #priv() {
    166    return 12;
    167  }
    168 
    169  efInFunction(str) {
    170    return (() => {
    171      let self = this;
    172      return evalInFrame(0, str);
    173    })();
    174  }
    175 }
    176 c = new C;
    177 assertEq(c.efInFunction(`self.#priv()`), 12);
    178 
    179 // JIT testing
    180 assertEq(b.ef(`
    181 let result;
    182 let f = () => {
    183  result = this.#priv();
    184  assertEq(result, 12);
    185 };
    186 for (let i = 0; i < 1000; i++) {
    187  f();
    188 }
    189 result
    190 `), 12);
    191 
    192 assertEq(b.ef("function f(o) { return o.callPriv() }; for (let i = 0; i < 1000; i++) { f(this); } f(this)"), 12);
    193 assertEq(b.ef("function f(o) { return o.callPrivF() }; for (let i = 0; i < 1000; i++) { f(this); } f(this)"), 12);
    194 assertEq(b.ef(`function x(o) { function y(o) { return o.#priv(); }; return y(o); } x(this)`), 12);
    195 
    196 assertEq(B.sef(`function f(o) { return o.#smethod() }; for (let i = 0; i < 1000; i ++) { f(this); }; f(this)`), 14);
    197 
    198 assertEq(b.ef(`
    199 var x = () => {
    200  return (() => {
    201    return (() => {
    202      let a;
    203      return (() => {
    204        let b = a;
    205        return this.#priv();
    206      })();
    207    })();
    208  })();
    209 };
    210 x()
    211 `), 12);