1 // TODO: count read bytes ourselves instead of relying on ftell()
2 #include "wasm_compile.h"
5 int leb_32(FILE *handle
, uint32_t *result
, bool with_sign
)
11 for (i
= 0; i
< 5; i
++) {
12 encoded
[i
] = fgetc(handle
);
14 if (encoded
[i
] == EOF
) {
23 PRERR(MSG_BAD_NUM_ENC
);
28 if (with_sign
&& encoded
[i
] & (1 << 6))
33 for (j
= i
; j
>= 0; j
--)
34 decoded
= (decoded
<< 7) | (encoded
[j
] & 0x7F);
36 if ((with_sign
&& decoded
> INT32_MAX
) ||
37 (with_sign
&& decoded
< INT32_MIN
) ||
38 (!with_sign
&& decoded
> UINT32_MAX
)) {
39 PRERR(MSG_BAD_NUM_ENC
);
48 void deinitialize_resulttype(struct resulttype
*type
)
55 void deinitialize_functype(struct functype
*type
)
57 deinitialize_resulttype(&type
->args
);
58 deinitialize_resulttype(&type
->results
);
61 void free_module(struct module
*module
)
68 for (i
= 0; i
< module
->functypes_count
; i
++)
69 deinitialize_functype(module
->functypes
+ i
);
71 free(module
->functypes
);
73 for (i
= 0; i
< module
->functions_count
; i
++) {
74 free(module
->functions
[i
].locals
);
75 free_expr(module
->functions
[i
].translated_body
);
78 free(module
->functions
);
80 for (i
= 0; i
< module
->exports_count
; i
++)
81 free(module
->exports
[i
].name
);
83 free(module
->exports
);
85 free_targets(module
->targets
);
87 free_expr(module
->startup
);
92 /* Guard against overflows on 32-bit systems */
93 static inline int safe_mul(size_t *factor1
, uint32_t factor2
)
100 if (product
> SIZE_MAX
) {
101 PRERR(MSG_SIZE_OVERFLOW
);
110 int parse_resulttype(FILE *handle
, struct resulttype
*type
)
115 if (leb_u32(handle
, &type
->count
)) {
121 type
->types
= malloc(type
->count
);
124 PRERR(MSG_ALLOC_FAIL(type
->count
));
134 readval
= fgetc(handle
);
136 if (readval
== EOF
) {
141 if (!is_valid_valtype(readval
)) {
142 PRERR(MSG_BAD("value type encoding", readval
));
146 type
->types
[i
] = readval
;
152 deinitialize_resulttype(type
);
157 int parse_functype(FILE *handle
, struct functype
*type
)
161 readval
= fgetc(handle
);
163 if (readval
== EOF
) {
168 if (readval
!= 0x60) {
169 PRERR(MSG_BAD("functype starting byte (0x60)", readval
));
173 if (parse_resulttype(handle
, &type
->args
) ||
174 parse_resulttype(handle
, &type
->results
)) {
175 deinitialize_functype(type
);
182 int parse_type_section(FILE *handle
, struct module
*module
)
184 uint32_t types_count
;
186 struct functype
*types
= NULL
;
187 uint32_t types_parsed
= 0;
189 if (leb_u32(handle
, &types_count
)) {
194 malloc_size
= sizeof(struct functype
);
196 if (safe_mul(&malloc_size
, types_count
)) {
201 types
= malloc(malloc_size
);
204 PRERR(MSG_ALLOC_FAIL(malloc_size
));
208 while (types_parsed
< types_count
) {
209 if (parse_functype(handle
, types
+ types_parsed
))
215 module
->functypes_count
= types_count
;
216 module
->functypes
= types
;
221 PRERR("Couldn't parse function types section\n");
224 while (types_parsed
--)
225 deinitialize_functype(types
+ types_parsed
);
233 int parse_function_section(FILE *handle
, struct module
*module
)
235 uint32_t funcs_count
;
237 struct function
*funcs
= NULL
;
241 if (leb_u32(handle
, &funcs_count
)) {
246 malloc_size
= sizeof(struct function
);
248 if (safe_mul(&malloc_size
, funcs_count
)) {
253 funcs
= malloc(malloc_size
);
256 PRERR(MSG_ALLOC_FAIL(malloc_size
));
260 for (i
= 0; i
< funcs_count
; i
++) {
261 if (leb_u32(handle
, &type_idx
)) {
266 if (type_idx
>= module
->functypes_count
) {
267 PRERR("Nonexistent function type index used");
271 if (module
->functypes
[type_idx
].results
.count
> 1) {
272 PRERR("Function returning more than one value\n");
276 funcs
[i
].type
= module
->functypes
+ type_idx
;
277 funcs
[i
].translated_body
= NULL
;
280 module
->functions_count
= funcs_count
;
281 module
->functions
= funcs
;
286 PRERR("Couldn't parse functions section");
293 static int parse_memory_section(FILE *handle
, struct module
*module
)
295 // TODO: move limits parsing to separate function?
296 uint32_t memories_count
;
299 if (leb_u32(handle
, &memories_count
)) {
304 if (memories_count
> 1) {
305 PRERR("More than one Wasm memory\n");
309 limits_type
= fgetc(handle
);
311 if (limits_type
== EOF
) {
316 if (leb_u32(handle
, &module
->mem_min
)) {
321 if (limits_type
== 0x00) {
322 module
->memory_type
= MEM_MIN
;
323 } else if (limits_type
== 0x01) {
324 if (leb_u32(handle
, &module
->mem_max
)) {
329 module
->memory_type
= MEM_MIN_MAX
;
331 PRERR(MSG_BAD("limit type", limits_type
));
343 static int parse_export_section(FILE *handle
, struct module
*module
)
346 uint32_t exports_count
;
348 struct export
*exports
= NULL
;
349 uint32_t exports_parsed
= 0;
353 if (leb_u32(handle
, &exports_count
)) {
358 malloc_size
= sizeof(struct export
);
360 if (safe_mul(&malloc_size
, exports_count
)) {
365 exports
= malloc(malloc_size
);
368 PRERR(MSG_ALLOC_FAIL(malloc_size
));
372 while (exports_parsed
< exports_count
) {
373 if (leb_u32(handle
, &name_len
)) {
378 name
= malloc(name_len
+ 1);
381 PRERR(MSG_ALLOC_FAIL(name_len
+ 1));
385 exports
[exports_parsed
].name
= name
;
386 /* Increment here, so that jump to fail: frees the name */
389 if (fread(name
, name_len
, 1, handle
) != 1) {
394 name
[name_len
] = '\0';
396 readval
= fgetc(handle
);
398 if (!is_valid_exportdesc(readval
)) {
399 PRERR(MSG_BAD("exportdesc", readval
));
403 exports
[exports_parsed
- 1].desc
= readval
;
405 if (leb_u32(handle
, &exports
[exports_parsed
- 1].idx
)) {
411 module
->exports_count
= exports_count
;
412 module
->exports
= exports
;
417 PRERR("Couldn't parse exports section\n");
420 while (exports_parsed
) {
421 free(exports
[exports_parsed
- 1].name
);
431 static int parse_function_code(FILE *handle
, struct function
*function
,
432 struct module
*module
)
435 uint32_t locals_blocks
;
436 uint32_t locals_count
= 0;
437 char *locals
= NULL
, *tmp
;
439 uint32_t locals_in_block
;
441 if (leb_u32(handle
, &locals_blocks
)) {
446 for (i
= 0; i
< locals_blocks
; i
++) {
447 if (leb_u32(handle
, &locals_in_block
)) {
452 if (locals_count
+ (uint64_t) locals_in_block
+
453 (uint64_t) function
->type
->args
.count
> UINT32_MAX
) {
454 PRERR("Too many locals\n");
458 locals_count
+= locals_in_block
;
460 if (locals_in_block
) {
461 tmp
= realloc(locals
, locals_count
);
464 PRERR(MSG_ALLOC_FAIL(locals_count
));
471 readval
= fgetc(handle
);
473 if (readval
== EOF
) {
478 if (!is_valid_valtype(readval
)) {
479 PRERR(MSG_BAD("value type encoding", readval
));
483 while (locals_in_block
)
484 locals
[locals_count
- locals_in_block
--] = readval
;
487 function
->translated_body
= NULL
;
489 function
->locals_count
= locals_count
;
490 function
->locals
= locals
;
492 if (translate(handle
, function
, module
))
503 int parse_code_section(FILE *handle
, struct module
*module
)
505 uint32_t functions_count
;
506 uint32_t functions_parsed
= 0;
507 uint32_t function_size
;
508 long function_start
, function_end
;
510 if (leb_u32(handle
, &functions_count
)) {
515 if (functions_count
!= module
->functions_count
) {
516 PRERR("Number of function bodies doesn't match number of functions\n");
520 while (functions_parsed
< functions_count
) {
521 if (leb_u32(handle
, &function_size
)) {
526 function_start
= ftell(handle
);
528 if (parse_function_code(handle
,
529 module
->functions
+ functions_parsed
,
531 PRERR("Couldn't parse code of function %lu\n",
532 (unsigned long) functions_parsed
);
536 function_end
= ftell(handle
);
538 if (function_end
- function_size
!= function_start
) {
539 PRERR("Function %lu started at offset %ld and should end at %ld, but ended at %ld\n",
540 (unsigned long) functions_parsed
,
541 function_start
, function_end
,
542 (long) (function_start
+ function_size
));
552 PRERR("Couldn't parse code section\n");
554 while (functions_parsed
) {
555 free(module
->functions
[functions_parsed
- 1].locals
);
556 free_expr(module
->functions
[functions_parsed
- 1]
558 module
->functions
[functions_parsed
- 1].translated_body
= NULL
;
566 static const char magic
[] = {0x00, 0x61, 0x73, 0x6D};
567 static const char version
[] = {0x01, 0x00, 0x00, 0x00};
569 struct module
*parse_module(FILE *handle
)
572 struct module
*module
= NULL
;
574 char highest_section_id
= 0;
575 uint32_t section_size
;
576 long section_start
, section_end
;
577 int (*section_parser
) (FILE*, struct module
*);
579 if (fread(initial
, 8, 1, handle
) != 1) {
584 /* check magic number */
585 if (memcmp(initial
, magic
, 4)) {
586 PRERR("Bad magic number\n");
591 if (memcmp(initial
+ 4, version
, 4)) {
592 PRERR("Unsupported Wasm version: 0x%02hhx 0x%02hhx 0x%02hhx 0x%02hhx\n",
593 initial
[4], initial
[5], initial
[6], initial
[7]);
597 module
= calloc(1, sizeof(struct module
));
600 PRERR(MSG_ALLOC_FAIL(sizeof(struct module
)));
605 section_id
= fgetc(handle
);
607 if (section_id
== EOF
)
610 if (leb_u32(handle
, §ion_size
)) {
615 section_start
= ftell(handle
);
617 if (section_id
== SECTION_CUSTOM
)
620 /* Sections are only allowed to appear in order */
621 if (section_id
<= highest_section_id
) {
622 PRERR("Sections out of order\n");
626 highest_section_id
= section_id
;
628 if (section_id
== SECTION_TYPE
) {
629 section_parser
= parse_type_section
;
630 } else if (section_id
== SECTION_FUNCTION
) {
631 section_parser
= parse_function_section
;
632 } else if (section_id
== SECTION_MEMORY
) {
633 section_parser
= parse_memory_section
;
634 } else if (section_id
== SECTION_EXPORT
) {
635 section_parser
= parse_export_section
;
636 } else if (section_id
== SECTION_CODE
) {
637 section_parser
= parse_code_section
;
639 PRERR("Unknown section id: %d\n", section_id
);
643 if (section_parser(handle
, module
))
646 section_end
= ftell(handle
);
648 if (section_end
- section_size
!= section_start
) {
649 PRERR("Section %d started at offset %ld and should end at %ld, but ended at %ld\n",
650 section_id
, section_start
, section_end
,
651 (long) (section_start
+ section_size
));
659 PRERR("Parsing failed\n");