aboutsummaryrefslogtreecommitdiff
path: root/src/corruptionCheck.js
blob: 0616337b401a5804a3b7d0c346cd4ee8df0aa17d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// See settings.js, CORRUPTION_CHECK

var CorruptionChecker = {
  BUFFER_FACTOR: {{{ CORRUPTION_CHECK }}},

  ptrs: {},

  init: function() {
    this.realMalloc = _malloc;
    _malloc = Module['_malloc'] = this.malloc;

    this.realFree = _free;
    _free = Module['_free'] = this.free;
  },
  malloc: function(size) {
    assert(size > 0); // some mallocs accept zero - fix your code if you want to use this tool
    var allocation = CorruptionChecker.realMalloc(size*(1+2*CorruptionChecker.BUFFER_FACTOR));
    var ptr = allocation + size*CorruptionChecker.BUFFER_FACTOR;
    assert(!CorruptionChecker.ptrs[ptr]);
    CorruptionChecker.ptrs[ptr] = size;
    CorruptionChecker.fillBuffer(allocation, size*CorruptionChecker.BUFFER_FACTOR);
    CorruptionChecker.fillBuffer(allocation + size*(1+CorruptionChecker.BUFFER_FACTOR), size*CorruptionChecker.BUFFER_FACTOR);
    return ptr;
  },
  free: function(ptr) {
    CorruptionChecker.checkPtr(ptr, true);
  },
  canary: function(x) {
    return (x + (x << 3) + (x&75) - (x&47))&255;
  },
  fillBuffer: function(allocation, size) {
    for (var x = allocation; x < allocation + size; x++) {
      {{{ makeSetValue('x', 0, 'CorruptionChecker.canary(x)', 'i8') }}};
    }
  },
  checkBuffer: function(allocation, size) {
    for (var x = allocation; x < allocation + size; x++) {
      assert(({{{ makeGetValue('x', 0, 'i8') }}}&255) == CorruptionChecker.canary(x), 'Heap corruption detected!');
    }
  },
  checkPtr: function(ptr, free) {
    var size = CorruptionChecker.ptrs[ptr];
    assert(size);
    var allocation = ptr - size*CorruptionChecker.BUFFER_FACTOR;
    CorruptionChecker.checkBuffer(allocation, size*CorruptionChecker.BUFFER_FACTOR);
    CorruptionChecker.checkBuffer(allocation + size*(1+CorruptionChecker.BUFFER_FACTOR), size*CorruptionChecker.BUFFER_FACTOR);
    if (free) {
      delete CorruptionChecker.ptrs[ptr];
      CorruptionChecker.realFree(allocation);
    }
  },
  checkAll: function() {
    for (var ptr in CorruptionChecker.ptrs) {
      CorruptionChecker.checkPtr(ptr, false);
    }
  },
};

CorruptionChecker.init();