summaryrefslogtreecommitdiff
path: root/src/wasm-validator.h
blob: 49e7a6a333a5fd6a8aa64f80ebeb531c2028c810 (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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

//
// Simple WebAssembly module validator.
//

#include "wasm.h"

namespace wasm {

struct WasmValidator : public WasmWalker {
  bool valid;

public:
  bool validate(Module& module) {
    valid = true;
    startWalk(&module);
    return valid;
  }

  // visitors

  void visitSetLocal(SetLocal *curr) override {
    shouldBeTrue(curr->type == curr->value->type);
  }
  void visitLoad(Load *curr) override {
    validateAlignment(curr->align);
  }
  void visitStore(Store *curr) override {
    validateAlignment(curr->align);
  }
  void visitSwitch(Switch *curr) override {
    std::set<Name> inTable;
    for (auto target : curr->targets) {
      if (target.is()) {
        inTable.insert(target);
      }
    }
    for (auto& c : curr->cases) {
      shouldBeFalse(c.name.is() && inTable.find(c.name) == inTable.end());
    }
    shouldBeFalse(curr->default_.is() && inTable.find(curr->default_) == inTable.end());
  }
  void visitMemory(Memory *curr) override {
    shouldBeFalse(curr->initial > curr->max);
    size_t top = 0;
    for (auto segment : curr->segments) {
      shouldBeFalse(segment.offset < top);
      top = segment.offset + segment.size;
    }
    shouldBeFalse(top > curr->initial);
  }
  void visitModule(Module *curr) override {
    for (auto& exp : curr->exports) {
      Name name = exp->name;
      bool found = false;
      for (auto& func : curr->functions) {
        if (func->name == name) {
          found = true;
          break;
        }
      }
      shouldBeTrue(found);
    }
  }

private:
  // helpers

  void shouldBeTrue(bool result) {
    if (!result) valid = false;
  }
  void shouldBeFalse(bool result) {
    if (result) valid = false;
  }

  void validateAlignment(size_t align) {
    switch (align) {
      case 1:
      case 2:
      case 4:
      case 8: break;
      default:{
        valid = false;
        break;
      }
    }
  }
};

} // namespace wasm