From 2a0275bd756878b43d560ee777e3f0aeabba8a4a Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Wed, 14 Apr 2021 21:54:09 +0300 Subject: [PATCH 1/5] More strict section order check --- source/m3_parse.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/source/m3_parse.c b/source/m3_parse.c index 6b29022..e3e5422 100644 --- a/source/m3_parse.c +++ b/source/m3_parse.c @@ -591,33 +591,32 @@ _ (Read_u32 (& version, & pos, end)); _throwif (m3Err_wasmMalformed, magic != 0x6d736100); _throwif (m3Err_incompatibleWasmVersion, version != 1); - m3log (parse, "found magic + version"); - u8 previousSection = 0; + + static const u8 sectionsOrder[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 10, 11, 0 }; // 0 is a placeholder + u8 expectedSection = 0; while (pos < end) { u8 section; _ (ReadLEB_u7 (& section, & pos, end)); - if (section > previousSection or // from the spec: sections must appear in order - section == 0 or // custom section - (section == 12 and previousSection == 9) or // if present, DataCount goes after Element - (section == 10 and previousSection == 12)) // and before Code - { - u32 sectionLength; -_ (ReadLEB_u32 (& sectionLength, & pos, end)); - _throwif(m3Err_wasmMalformed, pos + sectionLength > end); -_ (ParseModuleSection (module, section, pos, sectionLength)); + if (section != 0) { + // Ensure sections appear only once and in order + while (sectionsOrder[expectedSection++] != section) { + _throwif(m3Err_misorderedWasmSection, expectedSection >= 12); + } + } - pos += sectionLength; + u32 sectionLength; +_ (ReadLEB_u32 (& sectionLength, & pos, end)); + _throwif(m3Err_wasmMalformed, pos + sectionLength > end); - if (section) - previousSection = section; - } - else _throw (m3Err_misorderedWasmSection); +_ (ParseModuleSection (module, section, pos, sectionLength)); + + pos += sectionLength; } - } _catch: +} _catch: if (result) { From 33960e909a624144194301a43c8c40cec2be075e Mon Sep 17 00:00:00 2001 From: Steven Massey Date: Wed, 14 Apr 2021 11:55:41 -0700 Subject: [PATCH 2/5] debug mode slot validation --- source/m3_compile.c | 9 ++++++++ source/m3_info.c | 56 ++++++++++++++++++++++----------------------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/source/m3_compile.c b/source/m3_compile.c index e84330e..2c0f49d 100644 --- a/source/m3_compile.c +++ b/source/m3_compile.c @@ -352,6 +352,15 @@ u16 GetMaxUsedSlotPlusOne (IM3Compilation o) o->slotMaxAllocatedIndexPlusOne--; } + +# ifdef DEBUG + u16 maxSlot = o->slotMaxAllocatedIndexPlusOne; + while (maxSlot < d_m3MaxFunctionSlots) + { + d_m3Assert (o->m3Slots [maxSlot] == 0); + maxSlot++; + } +# endif return o->slotMaxAllocatedIndexPlusOne; } diff --git a/source/m3_info.c b/source/m3_info.c index 24a0a69..451a2fa 100644 --- a/source/m3_info.c +++ b/source/m3_info.c @@ -334,7 +334,7 @@ void dump_type_stack (IM3Compilation o) i32 regAllocated [2] = { (i32) IsRegisterAllocated (o, 0), (i32) IsRegisterAllocated (o, 1) }; // display whether r0 or fp0 is allocated. these should then also be reflected somewhere in the stack too. - d_m3Log(stack, "\n"); + d_m3Log(stack, "\n"); d_m3Log(stack, " "); printf ("%s %s ", regAllocated [0] ? "(r0)" : " ", regAllocated [1] ? "(fp0)" : " "); @@ -373,33 +373,33 @@ void dump_type_stack (IM3Compilation o) for (u32 r = 0; r < 2; ++r) d_m3Assert (regAllocated [r] == 0); // reg allocation & stack out of sync - - u16 maxSlot = GetMaxUsedSlotPlusOne (o); - - if (maxSlot > o->slotFirstDynamicIndex) - { - d_m3Log (stack, " -"); - - for (u16 i = o->slotFirstDynamicIndex; i < maxSlot; ++i) - printf ("----"); - - printf ("\n"); - - d_m3Log (stack, " slot |"); - for (u16 i = o->slotFirstDynamicIndex; i < maxSlot; ++i) - printf ("%3d|", i); - - printf ("\n"); - d_m3Log (stack, " alloc |"); - - for (u16 i = o->slotFirstDynamicIndex; i < maxSlot; ++i) - { - printf ("%3d|", o->m3Slots [i]); - } - - printf ("\n"); - } - d_m3Log(stack, "\n"); + + u16 maxSlot = GetMaxUsedSlotPlusOne (o); + + if (maxSlot > o->slotFirstDynamicIndex) + { + d_m3Log (stack, " -"); + + for (u16 i = o->slotFirstDynamicIndex; i < maxSlot; ++i) + printf ("----"); + + printf ("\n"); + + d_m3Log (stack, " slot |"); + for (u16 i = o->slotFirstDynamicIndex; i < maxSlot; ++i) + printf ("%3d|", i); + + printf ("\n"); + d_m3Log (stack, " alloc |"); + + for (u16 i = o->slotFirstDynamicIndex; i < maxSlot; ++i) + { + printf ("%3d|", o->m3Slots [i]); + } + + printf ("\n"); + } + d_m3Log(stack, "\n"); } From 835cdf05d2501c1412a07d034bcc999d4a1a18e4 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Thu, 15 Apr 2021 09:40:32 +0300 Subject: [PATCH 3/5] Fix missing imports detection --- source/m3_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/m3_module.c b/source/m3_module.c index f5abac6..c6a344c 100644 --- a/source/m3_module.c +++ b/source/m3_module.c @@ -105,7 +105,7 @@ IM3Function Module_GetFunction (IM3Module i_module, u32 i_functionIndex) if (i_functionIndex < i_module->numFunctions) { func = & i_module->functions [i_functionIndex]; - func->module = i_module; + //func->module = i_module; } return func; From e5c9dc68fda0ac126b49d1729d9682ee23c7b8f6 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Thu, 15 Apr 2021 18:33:23 +0300 Subject: [PATCH 4/5] Add wasm3-strace build for Win64. Closes #226 --- .github/workflows/publish.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b882400..1edc4cb 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,14 +18,17 @@ jobs: fail-fast: false matrix: config: - - {target: wasm3-win-x64, platform: "-A x64", toolset: "-T ClangCL" } - - {target: wasm3-win-x86, platform: "-A Win32", toolset: "-T ClangCL" } + - {target: wasm3-win-x64, platform: "-A x64", toolset: "-T ClangCL" } + - {target: wasm3-win-x86, platform: "-A Win32", toolset: "-T ClangCL" } + - {target: wasm3-strace-win-x64, platform: "-A x64", toolset: "-T ClangCL", cflags: "-DDEBUG -Dd_m3EnableStrace=2 -Dd_m3RecordBacktraces=1" } env: LDFLAGS: -s steps: - uses: actions/checkout@v2 - name: Configure + env: + CFLAGS: ${{ matrix.config.cflags }} run: | mkdir build cd build From 0e908d44351db5ebfdfdf61053119c7a152d1409 Mon Sep 17 00:00:00 2001 From: Volodymyr Shymanskyy Date: Thu, 15 Apr 2021 18:37:31 +0300 Subject: [PATCH 5/5] Fix OSS-Fuzz issues --- source/m3_compile.c | 2 ++ source/m3_env.h | 4 +--- source/m3_module.c | 4 ++++ source/m3_parse.c | 8 +++++--- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/source/m3_compile.c b/source/m3_compile.c index 2c0f49d..8f2a8a0 100644 --- a/source/m3_compile.c +++ b/source/m3_compile.c @@ -2399,6 +2399,8 @@ void SetupCompilation (IM3Compilation o) M3Result Compile_Function (IM3Function io_function) { + if (!io_function->wasm) return "function body is missing"; + IM3FuncType funcType = io_function->funcType; M3Result result = m3Err_none; m3log (compile, "compiling: '%s'; wasm-size: %d; numArgs: %d; return: %s", diff --git a/source/m3_env.h b/source/m3_env.h index 9d3a12f..5f5c482 100644 --- a/source/m3_env.h +++ b/source/m3_env.h @@ -89,9 +89,7 @@ typedef struct M3Module u32 numFuncTypes; IM3FuncType * funcTypes; // array of pointers to list of FuncTypes - u32 numImports; - //IM3Function * imports; b // notice: "I" prefix. imports are pointers to functions in another module. - + u32 numFuncImports; u32 numFunctions; M3Function * functions; diff --git a/source/m3_module.c b/source/m3_module.c index c6a344c..82e68d6 100644 --- a/source/m3_module.c +++ b/source/m3_module.c @@ -34,6 +34,10 @@ void m3_FreeModule (IM3Module i_module) m3_Free (i_module->dataSegments); m3_Free (i_module->table0); + for (u32 i = 0; i < i_module->numGlobals; ++i) + { + m3_Free (i_module->globals[i].name); + } for (u32 i = 0; i < i_module->numGlobals; ++i) { FreeImportInfo(&(i_module->globals[i].import)); diff --git a/source/m3_parse.c b/source/m3_parse.c index e3e5422..ca5c9d5 100644 --- a/source/m3_parse.c +++ b/source/m3_parse.c @@ -168,7 +168,7 @@ _ (ReadLEB_u32 (& typeIndex, & i_bytes, i_end)) _ (Module_AddFunction (io_module, typeIndex, & import)) import = clearImport; - io_module->numImports++; + io_module->numFuncImports++; } break; @@ -324,7 +324,7 @@ M3Result ParseSection_Code (M3Module * io_module, bytes_t i_bytes, cbytes_t i_ u32 numFunctions; _ (ReadLEB_u32 (& numFunctions, & i_bytes, i_end)); m3log (parse, "** Code [%d]", numFunctions); - if (numFunctions != io_module->numFunctions - io_module->numImports) + if (numFunctions != io_module->numFunctions - io_module->numFuncImports) { _throw ("mismatched function count in code section"); } @@ -361,7 +361,7 @@ _ (NormalizeType (& normalType, wasmType)); numLocals += varCount; m3log (parse, " %2d locals; type: '%s'", varCount, c_waTypes [normalType]); } - IM3Function func = Module_GetFunction (io_module, f + io_module->numImports); + IM3Function func = Module_GetFunction (io_module, f + io_module->numFuncImports); func->module = io_module; func->wasm = start; @@ -411,6 +411,8 @@ _ (ReadLEB_u32 (& segment->size, & i_bytes, i_end)); segment->data = i_bytes; m3log (parse, " segment [%u] memory: %u; expr-size: %d; size: %d", i, segment->memoryRegion, segment->initExprSize, segment->size); i_bytes += segment->size; + + _throwif("data segment underflow", i_bytes > i_end); } _catch: