Coverage Report

Created: 2025-07-01 06:18

/src/WasmEdge/lib/loader/ast/component/component.cpp
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: 2019-2024 Second State INC
3
4
#include "loader/loader.h"
5
6
using namespace std::literals;
7
8
namespace WasmEdge {
9
namespace Loader {
10
11
9.30k
Expect<std::pair<std::vector<Byte>, std::vector<Byte>>> Loader::loadPreamble() {
12
  // component ::= <preamble> s*:<section>* => (component flatten(s*))
13
  // preamble  ::= <magic> <version> <layer>
14
  // magic     ::= 0x00 0x61 0x73 0x6D
15
  // version   ::= 0x0a 0x00
16
  // layer     ::= 0x01 0x00
17
18
  // The combination of version and layer is corresponding to the version of
19
  // core wasm.
20
  // The core module has same magic but the different version:
21
  // 0x01 0x00 0x00 0x00
22
9.30k
  auto Magic = FMgr.readBytes(4);
23
9.30k
  if (!Magic) {
24
31
    return logLoadError(Magic.error(), FMgr.getLastOffset(),
25
31
                        ASTNodeAttr::Module);
26
31
  }
27
9.27k
  std::vector<Byte> WasmMagic = {0x00, 0x61, 0x73, 0x6D};
28
9.27k
  if (*Magic != WasmMagic) {
29
79
    auto M = *Magic;
30
79
    spdlog::error("Might an invalid wasm file, magic expected, but got 0x{:X} "
31
79
                  "0x{:X} 0x{:X} 0x{:X}"sv,
32
79
                  M[0], M[1], M[2], M[3]);
33
79
    return logLoadError(ErrCode::Value::MalformedMagic, FMgr.getLastOffset(),
34
79
                        ASTNodeAttr::Module);
35
79
  }
36
9.19k
  auto Ver = FMgr.readBytes(4);
37
9.19k
  if (!Ver) {
38
1
    return logLoadError(Ver.error(), FMgr.getLastOffset(), ASTNodeAttr::Module);
39
1
  }
40
9.19k
  return std::make_pair(*Magic, *Ver);
41
9.19k
}
42
43
Expect<void> Loader::loadComponent(AST::Component::Component &Comp,
44
0
                                   std::optional<uint64_t> Bound) {
45
0
  auto ReportError = [](auto E) {
46
0
    spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Component));
47
0
    return E;
48
0
  };
49
  // component ::= <preamble> s*:<section>*           => (component flatten(s*))
50
  // section   ::=    section_0(<core:custom>)        => ϵ
51
  //             | m: section_1(<core:module>)        => [core-prefix(m)]
52
  //             | i*:section_2(vec(<core:instance>)) => core-prefix(i)*
53
  //             | t*:section_3(vec(<core:type>))     => core-prefix(t)*
54
  //             | c: section_4(<component>)          => [c]
55
  //             | i*:section_5(vec(<instance>))      => i*
56
  //             | a*:section_6(vec(<alias>))         => a*
57
  //             | t*:section_7(vec(<type>))          => t*
58
  //             | c*:section_8(vec(<canon>))         => c*
59
  //             | s: section_9(<start>)              => [s]
60
  //             | i*:section_10(vec(<import>))       => i*
61
  //             | e*:section_11(vec(<export>))       => e*
62
  //             | v*:section_12(vec(<value>))        => v* 🪙
63
0
  uint64_t StartOffset = FMgr.getOffset();
64
0
  uint64_t Offset = FMgr.getOffset();
65
0
  Expect<Byte> ResSecId;
66
67
0
  while ((!Bound.has_value() || *Bound > Offset - StartOffset) &&
68
0
         (ResSecId = FMgr.readByte())) {
69
0
    if (!ResSecId) {
70
0
      return logLoadError(ResSecId.error(), FMgr.getLastOffset(),
71
0
                          ASTNodeAttr::Component);
72
0
    }
73
    // keep going only if we have new section ID
74
0
    uint8_t NewSectionId = *ResSecId;
75
0
    Comp.getSections().emplace_back();
76
0
    auto &Sec = Comp.getSections().back();
77
78
0
    switch (NewSectionId) {
79
0
    case 0x00:
80
0
      EXPECTED_TRY(loadSection(Sec.emplace<AST::CustomSection>())
81
0
                       .map_error(ReportError));
82
0
      break;
83
0
    case 0x01:
84
0
      EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::CoreModuleSection>())
85
0
                       .map_error(ReportError));
86
0
      break;
87
0
    case 0x02:
88
0
      EXPECTED_TRY(
89
0
          loadSection(Sec.emplace<AST::Component::CoreInstanceSection>())
90
0
              .map_error(ReportError));
91
0
      break;
92
0
    case 0x03:
93
0
      EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::CoreTypeSection>())
94
0
                       .map_error(ReportError));
95
0
      break;
96
0
    case 0x04:
97
0
      EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::ComponentSection>())
98
0
                       .map_error(ReportError));
99
0
      break;
100
0
    case 0x05:
101
0
      EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::InstanceSection>())
102
0
                       .map_error(ReportError));
103
0
      break;
104
0
    case 0x06:
105
0
      EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::AliasSection>())
106
0
                       .map_error(ReportError));
107
0
      break;
108
0
    case 0x07:
109
0
      EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::TypeSection>())
110
0
                       .map_error(ReportError));
111
0
      break;
112
0
    case 0x08:
113
0
      EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::CanonSection>())
114
0
                       .map_error(ReportError));
115
0
      break;
116
0
    case 0x09:
117
0
      EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::StartSection>())
118
0
                       .map_error(ReportError));
119
0
      break;
120
0
    case 0x0A:
121
0
      EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::ImportSection>())
122
0
                       .map_error(ReportError));
123
0
      break;
124
0
    case 0x0B:
125
0
      EXPECTED_TRY(loadSection(Sec.emplace<AST::Component::ExportSection>())
126
0
                       .map_error(ReportError));
127
0
      break;
128
0
    default:
129
0
      return logLoadError(ErrCode::Value::MalformedSection,
130
0
                          FMgr.getLastOffset(), ASTNodeAttr::Component);
131
0
    }
132
0
    Offset = FMgr.getOffset();
133
0
  }
134
0
  return {};
135
0
}
136
137
} // namespace Loader
138
} // namespace WasmEdge