Coverage Report

Created: 2025-11-15 06:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasm3/source/m3_parse.c
Line
Count
Source
1
//
2
//  m3_parse.c
3
//
4
//  Created by Steven Massey on 4/19/19.
5
//  Copyright © 2019 Steven Massey. All rights reserved.
6
//
7
8
#include "m3_env.h"
9
#include "m3_compile.h"
10
#include "m3_exception.h"
11
#include "m3_info.h"
12
13
14
M3Result  ParseType_Table  (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end)
15
0
{
16
0
    M3Result result = m3Err_none;
17
18
0
    return result;
19
0
}
20
21
22
M3Result  ParseType_Memory  (M3MemoryInfo * o_memory, bytes_t * io_bytes, cbytes_t i_end)
23
1.28k
{
24
1.28k
    M3Result result = m3Err_none;
25
26
1.28k
    u8 flag;
27
28
1.28k
_   (ReadLEB_u7 (& flag, io_bytes, i_end));                   // really a u1
29
1.28k
_   (ReadLEB_u32 (& o_memory->initPages, io_bytes, i_end));
30
31
1.28k
    o_memory->maxPages = 0;
32
1.28k
    if (flag & (1u << 0))
33
1.28k
_       (ReadLEB_u32 (& o_memory->maxPages, io_bytes, i_end));
34
35
1.28k
    o_memory->pageSize = 0;
36
1.28k
    if (flag & (1u << 3)) {
37
132
        u32 logPageSize;
38
132
_       (ReadLEB_u32 (& logPageSize, io_bytes, i_end));
39
132
        o_memory->pageSize = 1u << logPageSize;
40
132
    }
41
42
1.28k
    _catch: return result;
43
1.28k
}
44
45
46
M3Result  ParseSection_Type  (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end)
47
106
{
48
106
    IM3FuncType ftype = NULL;
49
50
106
_try {
51
106
    u32 numTypes;
52
106
_   (ReadLEB_u32 (& numTypes, & i_bytes, i_end));                                   m3log (parse, "** Type [%d]", numTypes);
53
54
105
    _throwif("too many types", numTypes > d_m3MaxSaneTypesCount);
55
56
105
    if (numTypes)
57
105
    {
58
        // table of IM3FuncType (that point to the actual M3FuncType struct in the Environment)
59
105
        io_module->funcTypes = m3_AllocArray (IM3FuncType, numTypes);
60
105
        _throwifnull (io_module->funcTypes);
61
105
        io_module->numFuncTypes = numTypes;
62
63
235
        for (u32 i = 0; i < numTypes; ++i)
64
158
        {
65
158
            i8 form;
66
158
_           (ReadLEB_i7 (& form, & i_bytes, i_end));
67
158
            _throwif (m3Err_wasmMalformed, form != -32); // for Wasm MVP
68
69
135
            u32 numArgs;
70
135
_           (ReadLEB_u32 (& numArgs, & i_bytes, i_end));
71
72
135
            _throwif (m3Err_tooManyArgsRets, numArgs > d_m3MaxSaneFunctionArgRetCount);
73
#if defined(M3_COMPILER_MSVC)
74
            u8 argTypes [d_m3MaxSaneFunctionArgRetCount];
75
#else
76
135
            u8 argTypes[numArgs+1]; // make ubsan happy
77
135
#endif
78
6.56k
            for (u32 a = 0; a < numArgs; ++a)
79
6.43k
            {
80
6.43k
                i8 wasmType;
81
6.43k
                u8 argType;
82
6.43k
_               (ReadLEB_i7 (& wasmType, & i_bytes, i_end));
83
6.43k
_               (NormalizeType (& argType, wasmType));
84
85
6.43k
                argTypes[a] = argType;
86
6.43k
            }
87
88
132
            u32 numRets;
89
132
_           (ReadLEB_u32 (& numRets, & i_bytes, i_end));
90
132
            _throwif (m3Err_tooManyArgsRets, (u64)(numRets) + numArgs > d_m3MaxSaneFunctionArgRetCount);
91
92
132
_           (AllocFuncType (& ftype, numRets + numArgs));
93
132
            ftype->numArgs = numArgs;
94
132
            ftype->numRets = numRets;
95
96
6.04k
            for (u32 r = 0; r < numRets; ++r)
97
5.91k
            {
98
5.91k
                i8 wasmType;
99
5.91k
                u8 retType;
100
5.91k
_               (ReadLEB_i7 (& wasmType, & i_bytes, i_end));
101
5.91k
_               (NormalizeType (& retType, wasmType));
102
103
5.91k
                ftype->types[r] = retType;
104
5.91k
            }
105
130
            memcpy (ftype->types + numRets, argTypes, numArgs);                                 m3log (parse, "    type %2d: %s", i, SPrintFuncTypeSignature (ftype));
106
107
130
            Environment_AddFuncType (io_module->environment, & ftype);
108
130
            io_module->funcTypes [i] = ftype;
109
130
            ftype = NULL; // ownership transferred to environment
110
130
        }
111
105
    }
112
113
106
} _catch:
114
115
106
    if (result)
116
29
    {
117
29
        m3_Free (ftype);
118
        // FIX: M3FuncTypes in the table are leaked
119
29
        m3_Free (io_module->funcTypes);
120
29
        io_module->numFuncTypes = 0;
121
29
    }
122
123
106
    return result;
124
105
}
125
126
127
M3Result  ParseSection_Function  (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end)
128
67
{
129
67
    M3Result result = m3Err_none;
130
131
67
    u32 numFunctions;
132
67
_   (ReadLEB_u32 (& numFunctions, & i_bytes, i_end));                               m3log (parse, "** Function [%d]", numFunctions);
133
134
67
    _throwif("too many functions", numFunctions > d_m3MaxSaneFunctionsCount);
135
136
67
_   (Module_PreallocFunctions(io_module, io_module->numFunctions + numFunctions));
137
138
1.02k
    for (u32 i = 0; i < numFunctions; ++i)
139
956
    {
140
956
        u32 funcTypeIndex;
141
956
_       (ReadLEB_u32 (& funcTypeIndex, & i_bytes, i_end));
142
143
956
_       (Module_AddFunction (io_module, funcTypeIndex, NULL /* import info */));
144
955
    }
145
146
67
    _catch: return result;
147
67
}
148
149
150
M3Result  ParseSection_Import  (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end)
151
28
{
152
28
    M3Result result = m3Err_none;
153
154
28
    M3ImportInfo import = { NULL, NULL }, clearImport = { NULL, NULL };
155
156
28
    u32 numImports;
157
28
_   (ReadLEB_u32 (& numImports, & i_bytes, i_end));                                 m3log (parse, "** Import [%d]", numImports);
158
159
28
    _throwif("too many imports", numImports > d_m3MaxSaneImportsCount);
160
161
    // Most imports are functions, so we won't waste much space anyway (if any)
162
28
_   (Module_PreallocFunctions(io_module, numImports));
163
164
3.88k
    for (u32 i = 0; i < numImports; ++i)
165
3.87k
    {
166
3.87k
        u8 importKind;
167
168
3.87k
_       (Read_utf8 (& import.moduleUtf8, & i_bytes, i_end));
169
3.87k
_       (Read_utf8 (& import.fieldUtf8, & i_bytes, i_end));
170
3.87k
_       (Read_u8 (& importKind, & i_bytes, i_end));                                 m3log (parse, "    kind: %d '%s.%s' ",
171
3.86k
                                                                                                (u32) importKind, import.moduleUtf8, import.fieldUtf8);
172
3.86k
        switch (importKind)
173
3.86k
        {
174
1.24k
            case d_externalKind_function:
175
1.24k
            {
176
1.24k
                u32 typeIndex;
177
1.24k
_               (ReadLEB_u32 (& typeIndex, & i_bytes, i_end))
178
179
1.24k
_               (Module_AddFunction (io_module, typeIndex, & import))
180
1.24k
                import = clearImport;
181
182
1.24k
                io_module->numFuncImports++;
183
1.24k
            }
184
0
            break;
185
186
724
            case d_externalKind_table:
187
//                  result = ParseType_Table (& i_bytes, i_end);
188
724
                break;
189
190
1.28k
            case d_externalKind_memory:
191
1.28k
            {
192
1.28k
_               (ParseType_Memory (& io_module->memoryInfo, & i_bytes, i_end));
193
1.28k
                io_module->memoryImported = true;
194
1.28k
                io_module->memoryImport = import;
195
1.28k
                import = clearImport;
196
1.28k
            }
197
0
            break;
198
199
603
            case d_externalKind_global:
200
603
            {
201
603
                i8 waType;
202
603
                u8 type, isMutable;
203
204
603
_               (ReadLEB_i7 (& waType, & i_bytes, i_end));
205
603
_               (NormalizeType (& type, waType));
206
603
_               (ReadLEB_u7 (& isMutable, & i_bytes, i_end));                     m3log (parse, "     global: %s mutable=%d", c_waTypes [type], (u32) isMutable);
207
208
603
                IM3Global global;
209
603
_               (Module_AddGlobal (io_module, & global, type, isMutable, true /* isImport */));
210
603
                global->import = import;
211
603
                import = clearImport;
212
603
            }
213
0
            break;
214
215
6
            default:
216
6
                _throw (m3Err_wasmMalformed);
217
3.86k
        }
218
219
3.85k
        FreeImportInfo (& import);
220
3.85k
    }
221
222
28
    _catch:
223
224
28
    FreeImportInfo (& import);
225
226
28
    return result;
227
28
}
228
229
230
M3Result  ParseSection_Export  (IM3Module io_module, bytes_t i_bytes, cbytes_t  i_end)
231
20
{
232
20
    M3Result result = m3Err_none;
233
20
    const char * utf8 = NULL;
234
235
20
    u32 numExports;
236
20
_   (ReadLEB_u32 (& numExports, & i_bytes, i_end));                                 m3log (parse, "** Export [%d]", numExports);
237
238
20
    _throwif("too many exports", numExports > d_m3MaxSaneExportsCount);
239
240
1.74k
    for (u32 i = 0; i < numExports; ++i)
241
1.73k
    {
242
1.73k
        u8 exportKind;
243
1.73k
        u32 index;
244
245
1.73k
_       (Read_utf8 (& utf8, & i_bytes, i_end));
246
1.73k
_       (Read_u8 (& exportKind, & i_bytes, i_end));
247
1.73k
_       (ReadLEB_u32 (& index, & i_bytes, i_end));                                  m3log (parse, "    index: %3d; kind: %d; export: '%s'; ", index, (u32) exportKind, utf8);
248
249
1.72k
        if (exportKind == d_externalKind_function)
250
419
        {
251
419
            _throwif(m3Err_wasmMalformed, index >= io_module->numFunctions);
252
415
            IM3Function func = &(io_module->functions [index]);
253
415
            if (func->numNames < d_m3MaxDuplicateFunctionImpl)
254
109
            {
255
109
                func->names[func->numNames++] = utf8;
256
109
                func->export_name = utf8;
257
109
                utf8 = NULL; // ownership transferred to M3Function
258
109
            }
259
415
        }
260
1.31k
        else if (exportKind == d_externalKind_global)
261
54
        {
262
54
            _throwif(m3Err_wasmMalformed, index >= io_module->numGlobals);
263
53
            IM3Global global = &(io_module->globals [index]);
264
53
            m3_Free (global->name);
265
53
            global->name = utf8;
266
53
            utf8 = NULL; // ownership transferred to M3Global
267
53
        }
268
1.25k
        else if (exportKind == d_externalKind_memory)
269
250
        {
270
250
            m3_Free (io_module->memoryExportName);
271
250
            io_module->memoryExportName = utf8;
272
250
            utf8 = NULL; // ownership transferred to M3Module
273
250
        }
274
1.00k
        else if (exportKind == d_externalKind_table)
275
464
        {
276
464
            m3_Free (io_module->table0ExportName);
277
464
            io_module->table0ExportName = utf8;
278
464
            utf8 = NULL; // ownership transferred to M3Module
279
464
        }
280
281
1.72k
        m3_Free (utf8);
282
1.72k
    }
283
284
20
_catch:
285
20
    m3_Free (utf8);
286
20
    return result;
287
20
}
288
289
290
M3Result  ParseSection_Start  (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end)
291
1
{
292
1
    M3Result result = m3Err_none;
293
294
1
    u32 startFuncIndex;
295
1
_   (ReadLEB_u32 (& startFuncIndex, & i_bytes, i_end));                               m3log (parse, "** Start Function: %d", startFuncIndex);
296
297
1
    if (startFuncIndex < io_module->numFunctions)
298
1
    {
299
1
        io_module->startFunction = startFuncIndex;
300
1
    }
301
0
    else result = "start function index out of bounds";
302
303
1
    _catch: return result;
304
1
}
305
306
307
M3Result  Parse_InitExpr  (M3Module * io_module, bytes_t * io_bytes, cbytes_t i_end)
308
374
{
309
374
    M3Result result = m3Err_none;
310
311
    // this doesn't generate code pages. just walks the wasm bytecode to find the end
312
313
#if defined(d_m3PreferStaticAlloc)
314
    static M3Compilation compilation;
315
#else
316
374
    M3Compilation compilation;
317
374
#endif
318
374
    compilation = (M3Compilation){ .runtime = NULL, .module = io_module, .wasm = * io_bytes, .wasmEnd = i_end };
319
320
374
    result = CompileBlockStatements (& compilation);
321
322
374
    * io_bytes = compilation.wasm;
323
324
374
    return result;
325
374
}
326
327
328
M3Result  ParseSection_Element  (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end)
329
1
{
330
1
    M3Result result = m3Err_none;
331
332
1
    u32 numSegments;
333
1
_   (ReadLEB_u32 (& numSegments, & i_bytes, i_end));                         m3log (parse, "** Element [%d]", numSegments);
334
335
1
    _throwif ("too many element segments", numSegments > d_m3MaxSaneElementSegments);
336
337
1
    io_module->elementSection = i_bytes;
338
1
    io_module->elementSectionEnd = i_end;
339
1
    io_module->numElementSegments = numSegments;
340
341
1
    _catch: return result;
342
1
}
343
344
345
M3Result  ParseSection_Code  (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end)
346
50
{
347
50
    M3Result result;
348
349
50
    u32 numFunctions;
350
50
_   (ReadLEB_u32 (& numFunctions, & i_bytes, i_end));                               m3log (parse, "** Code [%d]", numFunctions);
351
352
50
    if (numFunctions != io_module->numFunctions - io_module->numFuncImports)
353
1
    {
354
1
        _throw ("mismatched function count in code section");
355
0
    }
356
357
235
    for (u32 f = 0; f < numFunctions; ++f)
358
187
    {
359
187
        const u8 * start = i_bytes;
360
361
187
        u32 size;
362
187
_       (ReadLEB_u32 (& size, & i_bytes, i_end));
363
364
187
        if (size)
365
49
        {
366
49
            const u8 * ptr = i_bytes;
367
49
            i_bytes += size;
368
369
49
            if (i_bytes <= i_end)
370
48
            {
371
                /*
372
                u32 numLocalBlocks;
373
_               (ReadLEB_u32 (& numLocalBlocks, & ptr, i_end));                                      m3log (parse, "    code size: %-4d", size);
374
375
                u32 numLocals = 0;
376
377
                for (u32 l = 0; l < numLocalBlocks; ++l)
378
                {
379
                    u32 varCount;
380
                    i8 wasmType;
381
                    u8 normalType;
382
383
_                   (ReadLEB_u32 (& varCount, & ptr, i_end));
384
_                   (ReadLEB_i7 (& wasmType, & ptr, i_end));
385
_                   (NormalizeType (& normalType, wasmType));
386
387
                    numLocals += varCount;                                                      m3log (parse, "      %2d locals; type: '%s'", varCount, c_waTypes [normalType]);
388
                }
389
                 */
390
391
48
                IM3Function func = Module_GetFunction (io_module, f + io_module->numFuncImports);
392
393
48
                func->module = io_module;
394
48
                func->wasm = start;
395
48
                func->wasmEnd = i_bytes;
396
                //func->ownsWasmCode = io_module->hasWasmCodeCopy;
397
//                func->numLocals = numLocals;
398
48
            }
399
48
            else _throw (m3Err_wasmSectionOverrun);
400
48
        }
401
187
    }
402
403
50
    _catch:
404
405
50
    if (not result and i_bytes != i_end)
406
0
        result = m3Err_wasmSectionUnderrun;
407
408
50
    return result;
409
49
}
410
411
412
M3Result  ParseSection_Data  (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end)
413
48
{
414
48
    M3Result result = m3Err_none;
415
416
48
    u32 numDataSegments;
417
48
_   (ReadLEB_u32 (& numDataSegments, & i_bytes, i_end));                            m3log (parse, "** Data [%d]", numDataSegments);
418
419
48
    _throwif("too many data segments", numDataSegments > d_m3MaxSaneDataSegments);
420
421
48
    io_module->dataSegments = m3_AllocArray (M3DataSegment, numDataSegments);
422
48
    _throwifnull(io_module->dataSegments);
423
48
    io_module->numDataSegments = numDataSegments;
424
425
227
    for (u32 i = 0; i < numDataSegments; ++i)
426
191
    {
427
191
        M3DataSegment * segment = & io_module->dataSegments [i];
428
429
191
_       (ReadLEB_u32 (& segment->memoryRegion, & i_bytes, i_end));
430
431
191
        segment->initExpr = i_bytes;
432
191
_       (Parse_InitExpr (io_module, & i_bytes, i_end));
433
179
        segment->initExprSize = (u32) (i_bytes - segment->initExpr);
434
435
179
        _throwif (m3Err_wasmMissingInitExpr, segment->initExprSize <= 1);
436
437
179
_       (ReadLEB_u32 (& segment->size, & i_bytes, i_end));
438
179
        segment->data = i_bytes;                                                    m3log (parse, "    segment [%u]  memory: %u;  expr-size: %d;  size: %d",
439
179
                                                                                       i, segment->memoryRegion, segment->initExprSize, segment->size);
440
179
        i_bytes += segment->size;
441
442
179
        _throwif("data segment underflow", i_bytes > i_end);
443
179
    }
444
445
48
    _catch:
446
447
48
    return result;
448
48
}
449
450
451
M3Result  ParseSection_Memory  (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end)
452
0
{
453
0
    M3Result result = m3Err_none;
454
455
    // TODO: MVP; assert no memory imported
456
457
0
    u32 numMemories;
458
0
_   (ReadLEB_u32 (& numMemories, & i_bytes, i_end));                             m3log (parse, "** Memory [%d]", numMemories);
459
460
0
    _throwif (m3Err_tooManyMemorySections, numMemories != 1);
461
462
0
    ParseType_Memory (& io_module->memoryInfo, & i_bytes, i_end);
463
464
0
    _catch: return result;
465
0
}
466
467
468
M3Result  ParseSection_Global  (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end)
469
14
{
470
14
    M3Result result = m3Err_none;
471
472
14
    u32 numGlobals;
473
14
_   (ReadLEB_u32 (& numGlobals, & i_bytes, i_end));                                 m3log (parse, "** Global [%d]", numGlobals);
474
475
14
    _throwif("too many globals", numGlobals > d_m3MaxSaneGlobalsCount);
476
477
191
    for (u32 i = 0; i < numGlobals; ++i)
478
184
    {
479
184
        i8 waType;
480
184
        u8 type, isMutable;
481
482
184
_       (ReadLEB_i7 (& waType, & i_bytes, i_end));
483
184
_       (NormalizeType (& type, waType));
484
183
_       (ReadLEB_u7 (& isMutable, & i_bytes, i_end));                                 m3log (parse, "    global: [%d] %s mutable: %d", i, c_waTypes [type],   (u32) isMutable);
485
486
183
        IM3Global global;
487
183
_       (Module_AddGlobal (io_module, & global, type, isMutable, false /* isImport */));
488
489
183
        global->initExpr = i_bytes;
490
183
_       (Parse_InitExpr (io_module, & i_bytes, i_end));
491
178
        global->initExprSize = (u32) (i_bytes - global->initExpr);
492
493
178
        _throwif (m3Err_wasmMissingInitExpr, global->initExprSize <= 1);
494
177
    }
495
496
14
    _catch: return result;
497
14
}
498
499
500
M3Result  ParseSection_Name  (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end)
501
729
{
502
729
    M3Result result;
503
504
729
    cstr_t name;
505
506
1.84k
    while (i_bytes < i_end)
507
1.12k
    {
508
1.12k
        u8 nameType;
509
1.12k
        u32 payloadLength;
510
511
1.12k
_       (ReadLEB_u7 (& nameType, & i_bytes, i_end));
512
1.12k
_       (ReadLEB_u32 (& payloadLength, & i_bytes, i_end));
513
514
1.12k
        bytes_t start = i_bytes;
515
1.12k
        if (nameType == 1)
516
374
        {
517
374
            u32 numNames;
518
374
_           (ReadLEB_u32 (& numNames, & i_bytes, i_end));
519
520
374
            _throwif("too many names", numNames > d_m3MaxSaneFunctionsCount);
521
522
1.46k
            for (u32 i = 0; i < numNames; ++i)
523
1.09k
            {
524
1.09k
                u32 index;
525
1.09k
_               (ReadLEB_u32 (& index, & i_bytes, i_end));
526
1.09k
_               (Read_utf8 (& name, & i_bytes, i_end));
527
528
1.08k
                if (index < io_module->numFunctions)
529
399
                {
530
399
                    IM3Function func = &(io_module->functions [index]);
531
399
                    if (func->numNames == 0)
532
107
                    {
533
107
                        func->names[0] = name;        m3log (parse, "    naming function%5d:  %s", index, name);
534
107
                        func->numNames = 1;
535
107
                        name = NULL; // transfer ownership
536
107
                    }
537
//                          else m3log (parse, "prenamed: %s", io_module->functions [index].name);
538
399
                }
539
540
1.08k
                m3_Free (name);
541
1.08k
            }
542
374
        }
543
544
1.11k
        i_bytes = start + payloadLength;
545
1.11k
    }
546
547
729
    _catch: return result;
548
729
}
549
550
551
M3Result  ParseSection_Custom  (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end)
552
1.76k
{
553
1.76k
    M3Result result;
554
555
1.76k
    cstr_t name;
556
1.76k
_   (Read_utf8 (& name, & i_bytes, i_end));
557
1.75k
                                                                                    m3log (parse, "** Custom: '%s'", name);
558
1.75k
    if (strcmp (name, "name") == 0) {
559
729
_       (ParseSection_Name(io_module, i_bytes, i_end));
560
1.02k
    } else if (io_module->environment->customSectionHandler) {
561
0
_       (io_module->environment->customSectionHandler(io_module, name, i_bytes, i_end));
562
0
    }
563
564
1.74k
    m3_Free (name);
565
566
1.76k
    _catch: return result;
567
1.74k
}
568
569
570
M3Result  ParseModuleSection  (M3Module * o_module, u8 i_sectionType, bytes_t i_bytes, u32 i_numBytes)
571
2.09k
{
572
2.09k
    M3Result result = m3Err_none;
573
574
2.09k
    typedef M3Result (* M3Parser) (M3Module *, bytes_t, cbytes_t);
575
576
2.09k
    static M3Parser s_parsers [] =
577
2.09k
    {
578
2.09k
        ParseSection_Custom,    // 0
579
2.09k
        ParseSection_Type,      // 1
580
2.09k
        ParseSection_Import,    // 2
581
2.09k
        ParseSection_Function,  // 3
582
2.09k
        NULL,                   // 4: TODO Table
583
2.09k
        ParseSection_Memory,    // 5
584
2.09k
        ParseSection_Global,    // 6
585
2.09k
        ParseSection_Export,    // 7
586
2.09k
        ParseSection_Start,     // 8
587
2.09k
        ParseSection_Element,   // 9
588
2.09k
        ParseSection_Code,      // 10
589
2.09k
        ParseSection_Data,      // 11
590
2.09k
        NULL,                   // 12: TODO DataCount
591
2.09k
    };
592
593
2.09k
    M3Parser parser = NULL;
594
595
2.09k
    if (i_sectionType <= 12)
596
2.09k
        parser = s_parsers [i_sectionType];
597
598
2.09k
    if (parser)
599
2.09k
    {
600
2.09k
        cbytes_t end = i_bytes + i_numBytes;
601
2.09k
        result = parser (o_module, i_bytes, end);
602
2.09k
    }
603
2
    else
604
2
    {
605
2
        m3log (parse, " skipped section type: %d", (u32) i_sectionType);
606
2
    }
607
608
2.09k
    return result;
609
2.09k
}
610
611
612
M3Result  m3_ParseModule  (IM3Environment i_environment, IM3Module * o_module, cbytes_t i_bytes, u32 i_numBytes)
613
209
{
614
209
    IM3Module module;                                                               m3log (parse, "load module: %d bytes", i_numBytes);
615
209
_try {
616
209
    module = m3_AllocStruct (M3Module);
617
209
    _throwifnull (module);
618
209
    module->name = ".unnamed";                                                      m3log (parse, "load module: %d bytes", i_numBytes);
619
209
    module->startFunction = -1;
620
    //module->hasWasmCodeCopy = false;
621
209
    module->environment = i_environment;
622
623
209
    const u8 * pos = i_bytes;
624
209
    const u8 * end = pos + i_numBytes;
625
626
209
    module->wasmStart = pos;
627
209
    module->wasmEnd = end;
628
629
209
    u32 magic, version;
630
209
_   (Read_u32 (& magic, & pos, end));
631
209
_   (Read_u32 (& version, & pos, end));
632
633
209
    _throwif (m3Err_wasmMalformed, magic != 0x6d736100);
634
205
    _throwif (m3Err_incompatibleWasmVersion, version != 1);
635
636
205
    static const u8 sectionsOrder[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 10, 11, 0 }; // 0 is a placeholder
637
205
    u8 expectedSection = 0;
638
639
2.21k
    while (pos < end)
640
2.10k
    {
641
2.10k
        u8 section;
642
2.10k
_       (ReadLEB_u7 (& section, & pos, end));
643
644
2.10k
        if (section != 0) {
645
            // Ensure sections appear only once and in order
646
1.43k
            while (sectionsOrder[expectedSection++] != section) {
647
1.09k
                _throwif(m3Err_misorderedWasmSection, expectedSection >= 12);
648
1.09k
            }
649
341
        }
650
651
2.10k
        u32 sectionLength;
652
2.10k
_       (ReadLEB_u32 (& sectionLength, & pos, end));
653
2.10k
        _throwif(m3Err_wasmMalformed, pos + sectionLength > end);
654
655
2.09k
_       (ParseModuleSection (module, section, pos, sectionLength));
656
657
2.00k
        pos += sectionLength;
658
2.00k
    }
659
660
209
} _catch:
661
662
209
    if (result)
663
104
    {
664
104
        m3_FreeModule (module);
665
104
        module = NULL;
666
104
    }
667
668
209
    * o_module = module;
669
670
209
    return result;
671
205
}