diff options
Diffstat (limited to 'tools/parse_module.c')
-rw-r--r-- | tools/parse_module.c | 172 |
1 files changed, 91 insertions, 81 deletions
diff --git a/tools/parse_module.c b/tools/parse_module.c index 155fc9c..75329f8 100644 --- a/tools/parse_module.c +++ b/tools/parse_module.c @@ -68,6 +68,19 @@ int leb_u32(FILE *handle, uint32_t *result) return 0; } +void deinitialize_resulttype(struct resulttype *type) +{ + type->count = 0; + free(type->types); + type->types = NULL; +} + +void deinitialize_functype(struct functype *type) +{ + deinitialize_resulttype(&type->args); + deinitialize_resulttype(&type->results); +} + void free_module(struct module *module) { size_t i; @@ -76,7 +89,7 @@ void free_module(struct module *module) return; for (i = 0; i < module->functypes_count; i++) - free(module->functypes[i].arguments); + deinitialize_functype(module->functypes + i); free(module->functypes); @@ -113,37 +126,30 @@ static inline int safe_mul(size_t *factor1, uint32_t factor2) return 0; } -int parse_type_section(FILE *handle, struct module *module) +int parse_resulttype(FILE *handle, struct resulttype *type) { - uint32_t types_count; int readval; - size_t malloc_size; - struct functype *types = NULL; - uint32_t types_parsed = 0; - uint32_t args_count; - char *args; uint32_t i; - if (leb_u32(handle, &types_count)) { + if (leb_u32(handle, &type->count)) { PRERR(MSG_BAD_NUM); goto fail; } - malloc_size = sizeof(struct functype); + if (type->count) { + type->types = malloc(type->count); - if (safe_mul(&malloc_size, types_count)) { - PRERR(MSG_BAD_SIZE); - goto fail; + if (!type->types) { + PRERR(MSG_ALLOC_FAIL(type->count)); + goto fail; + } + } else { + type->types = NULL; } - types = malloc(malloc_size); - - if (!types) { - PRERR(MSG_ALLOC_FAIL(malloc_size)); - goto fail; - } + i = type->count; - while (types_parsed < types_count) { + while (i--) { readval = fgetc(handle); if (readval == EOF) { @@ -151,77 +157,78 @@ int parse_type_section(FILE *handle, struct module *module) goto fail; } - if (readval != 0x60) { - PRERR(MSG_BAD("functype starting byte (0x60)", - readval)); + if (!is_valid_valtype(readval)) { + PRERR(MSG_BAD("value type encoding", readval)); goto fail; } - if (leb_u32(handle, &args_count)) { - PRERR(MSG_BAD_NUM); - goto fail; - } + type->types[i] = readval; + } - if (args_count) { - args = malloc(args_count); + return 0; - if (!args) { - PRERR(MSG_ALLOC_FAIL(args_count)); - goto fail; - } - } else { - args = NULL; - } +fail: + deinitialize_resulttype(type); - types[types_parsed].arguments_count = args_count; - types[types_parsed].arguments = args; - /* Increment here, so that jump to fail: frees the args */ - types_parsed++; + return -1; +} - for (i = 0; i < args_count; i++) { - readval = fgetc(handle); +int parse_functype(FILE *handle, struct functype *type) +{ + int readval; - if (readval == EOF) { - PRERR(MSG_EOF); - goto fail; - } + readval = fgetc(handle); - if (!is_valid_valtype(readval)) { - PRERR(MSG_BAD("value type encoding", readval)); - goto fail; - } + if (readval == EOF) { + PRERR(MSG_EOF); + return -1; + } - args[i] = readval; - } + if (readval != 0x60) { + PRERR(MSG_BAD("functype starting byte (0x60)", readval)); + return -1; + } - readval = fgetc(handle); + if (parse_resulttype(handle, &type->args) || + parse_resulttype(handle, &type->results)) { + deinitialize_functype(type); + return -1; + } - if (readval == EOF) { - PRERR(MSG_EOF); - goto fail; - } + return 0; +} - if (readval == 0x00) { - types[types_parsed - 1].result = 0; - } else if (readval == 0x01) { +int parse_type_section(FILE *handle, struct module *module) +{ + uint32_t types_count; + size_t malloc_size; + struct functype *types = NULL; + uint32_t types_parsed = 0; - readval = fgetc(handle); + if (leb_u32(handle, &types_count)) { + PRERR(MSG_BAD_NUM); + goto fail; + } - if (readval == EOF) { - PRERR(MSG_EOF); - goto fail; - } + malloc_size = sizeof(struct functype); - if (!is_valid_valtype(readval)) { - PRERR(MSG_BAD("value type encoding", readval)); - goto fail; - } + if (safe_mul(&malloc_size, types_count)) { + PRERR(MSG_BAD_SIZE); + goto fail; + } - types[types_parsed - 1].result = readval; - } else { - PRERR(MSG_BAD("return values count", readval)); + types = malloc(malloc_size); + + if (!types) { + PRERR(MSG_ALLOC_FAIL(malloc_size)); + goto fail; + } + + while (types_parsed < types_count) { + if (parse_functype(handle, types + types_parsed)) goto fail; - } + + types_parsed++; } module->functypes_count = types_count; @@ -233,10 +240,8 @@ fail: PRERR("Couldn't parse function types section\n"); if (types) { - while (types_parsed) { - free(types[types_parsed - 1].arguments); - types_parsed--; - } + while (types_parsed--) + deinitialize_functype(types + types_parsed); free(types); } @@ -282,7 +287,12 @@ int parse_function_section(FILE *handle, struct module *module) goto fail; } - funcs[i].type = module->functypes + i; + if (module->functypes[type_idx].results.count > 1) { + PRERR("Function returning more than one value\n"); + goto fail; + } + + funcs[i].type = module->functypes + type_idx; funcs[i].translated_body = NULL; } @@ -444,7 +454,6 @@ static int parse_function_code(FILE *handle, struct function *function, uint32_t locals_blocks; uint32_t locals_count = 0; char *locals = NULL, *tmp; - char *body = NULL; uint32_t i; uint32_t locals_in_block; @@ -459,7 +468,8 @@ static int parse_function_code(FILE *handle, struct function *function, goto fail; } - if (locals_count + (uint64_t) locals_in_block > UINT32_MAX) { + if (locals_count + (uint64_t) locals_in_block + + (uint64_t) function->type->args.count > UINT32_MAX) { PRERR("Too many locals\n"); goto fail; } @@ -505,7 +515,6 @@ static int parse_function_code(FILE *handle, struct function *function, fail: free(locals); - free(body); return -1; } @@ -565,6 +574,7 @@ fail: free(module->functions[functions_parsed - 1].locals); free_expr(module->functions[functions_parsed - 1] .translated_body); + module->functions[functions_parsed - 1].translated_body = NULL; functions_parsed--; } |