commit 2ffc3196f199e93c00b1bde9f937d7efb587146e parent 9048ce748f804c96ea61d27b2139edd8d4548428 Author: Kiƫd Llaentenn <kiedtl@tilde.team> Date: Tue, 13 Apr 2021 21:03:25 +0000 Fix stack overflow in is_zeroes() When a large buffer is declared as a global variable, e.g.: def IMAGE_SIZE: size = 242000; let memory: [IMAGE_SIZE]i32 = [0...]; ...is_zeroes() overflows its stack when the stack is smaller than the buffer's size. Converting is_zeroes() to an iterative function instead of a recursive one fixes this issue. Diffstat:
M | src/emit.c | | | 47 | +++++++++++++++++++++++------------------------ |
1 file changed, 23 insertions(+), 24 deletions(-)
diff --git a/src/emit.c b/src/emit.c @@ -254,36 +254,35 @@ emit_data_string(const char *str, size_t sz, FILE *out) static bool is_zeroes(struct qbe_data_item *data) { - switch (data->type) { - case QD_ZEROED: - break; - case QD_VALUE: - switch (data->value.kind) { - case QV_CONST: - if (data->value.lval != 0) { + for (struct qbe_data_item *cur = data; cur; cur = cur->next) { + switch (cur->type) { + case QD_ZEROED: + break; + case QD_VALUE: + switch (cur->value.kind) { + case QV_CONST: + if (cur->value.lval != 0) { + return false; + } + break; + case QV_GLOBAL: + case QV_LABEL: + case QV_TEMPORARY: return false; } break; - case QV_GLOBAL: - case QV_LABEL: - case QV_TEMPORARY: - return false; - } - break; - case QD_STRING: - for (size_t i = 0; i < data->sz; ++i) { - if (data->str[i] != 0) { - return false; + case QD_STRING: + for (size_t i = 0; i < cur->sz; ++i) { + if (cur->str[i] != 0) { + return false; + } } + break; + case QD_SYMOFFS: + return false; } - break; - case QD_SYMOFFS: - return false; - } - if (!data->next) { - return true; } - return is_zeroes(data->next); + return true; } static void