summaryrefslogtreecommitdiff
path: root/src/s2wasm.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/s2wasm.h')
-rw-r--r--src/s2wasm.h86
1 files changed, 65 insertions, 21 deletions
diff --git a/src/s2wasm.h b/src/s2wasm.h
index bd3f12e73..b99a71159 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -160,19 +160,36 @@ private:
}
int32_t getInt() {
- int32_t ret = 0;
+ const char* loc = s;
+ uint32_t value = 0;
bool neg = false;
- if (*s == '-') {
+ if (*loc == '-') {
neg = true;
- s++;
+ loc++;
}
- while (isdigit(*s)) {
- ret *= 10;
- ret += (*s - '0');
- s++;
+ while (isdigit(*loc)) {
+ uint32_t digit = *loc - '0';
+ if (value > std::numeric_limits<uint32_t>::max() / 10) {
+ abort_on("uint32_t overflow");
+ }
+ value *= 10;
+ if (value > std::numeric_limits<uint32_t>::max() - digit) {
+ abort_on("uint32_t overflow");
+ }
+ value += digit;
+ loc++;
}
- if (neg) ret = -ret;
- return ret;
+ if (neg) {
+ uint32_t positive_int_min =
+ (uint32_t) - (1 + std::numeric_limits<int32_t>::min()) + (uint32_t)1;
+ if (value > positive_int_min) {
+ abort_on("negative int32_t overflow");
+ }
+ s = loc;
+ return -value;
+ }
+ s = loc;
+ return value;
}
// gets a constant, which may be a relocation for later.
@@ -183,7 +200,7 @@ private:
return false;
} else {
// a global constant, we need to fix it up later
- Name name = getStrToSep();
+ Name name = cleanFunction(getStrToSep());
int offset = 0;
if (*s == '+') {
s++;
@@ -198,19 +215,36 @@ private:
}
int64_t getInt64() {
- int64_t ret = 0;
+ const char* loc = s;
+ uint64_t value = 0;
bool neg = false;
- if (*s == '-') {
+ if (*loc == '-') {
neg = true;
- s++;
+ loc++;
}
- while (isdigit(*s)) {
- ret *= 10;
- ret += (*s - '0');
- s++;
+ while (isdigit(*loc)) {
+ uint64_t digit = *loc - '0';
+ if (value > std::numeric_limits<uint64_t>::max() / 10) {
+ abort_on("uint64_t overflow");
+ }
+ value *= 10;
+ if (value > std::numeric_limits<uint64_t>::max() - digit) {
+ abort_on("uint64_t overflow");
+ }
+ value += digit;
+ loc++;
}
- if (neg) ret = -ret;
- return ret;
+ if (neg) {
+ uint64_t positive_int_min =
+ (uint64_t) - (1 + std::numeric_limits<int64_t>::min()) + (uint64_t)1;
+ if (value > positive_int_min) {
+ abort_on("negative int64_t overflow");
+ }
+ s = loc;
+ return -value;
+ }
+ s = loc;
+ return value;
}
Name getCommaSeparated() {
@@ -282,6 +316,16 @@ private:
abort_on("getType");
}
+ // The LLVM backend emits function names as name@FUNCTION. We can drop the @ and after it.
+ Name cleanFunction(Name name) {
+ if (!strchr(name.str, '@')) return name;
+ char *temp = strdup(name.str);
+ *strchr(temp, '@') = 0;
+ Name ret = cashew::IString(temp, false);
+ free(temp);
+ return ret;
+ }
+
// processors
void scan() {
@@ -543,7 +587,7 @@ private:
curr = specific;
} else {
assign = getAssign();
- Name target = getCommaSeparated();
+ Name target = cleanFunction(getCommaSeparated());
if (implementedFunctions.count(target) > 0) {
auto specific = allocator.alloc<Call>();
specific->target = target;
@@ -933,7 +977,7 @@ private:
} else if (match(".int64")) {
size_t size = raw->size();
raw->resize(size + 8);
- (*(int64_t*)(&(*raw)[size])) = getInt();
+ (*(int64_t*)(&(*raw)[size])) = getInt64();
zero = false;
} else {
break;