Coverage Report

Created: 2026-08-13 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/lib/loader/ast/section.cpp
Line
Count
Source
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright The WasmEdge Authors
3
4
#include "aot/version.h"
5
#include "common/defines.h"
6
#include "loader/loader.h"
7
8
#include <tuple>
9
#include <utility>
10
11
using namespace std::literals;
12
13
namespace WasmEdge {
14
namespace Loader {
15
16
// Load content of custom section. See "include/loader/loader.h".
17
1.39M
Expect<void> Loader::loadSection(AST::CustomSection &Sec) {
18
1.39M
  return loadSectionContent(Sec, [this, &Sec]() -> Expect<void> {
19
1.39M
    auto ReportError = [this](auto E) {
20
187
      return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Sec_Custom);
21
187
    };
22
23
    // Read name.
24
1.39M
    auto StartOffset = FMgr.getOffset();
25
1.39M
    EXPECTED_TRY(std::string Name, FMgr.readName().map_error(ReportError));
26
1.39M
    Sec.setName(Name);
27
1.39M
    auto ReadSize = FMgr.getOffset() - StartOffset;
28
29
    // Check for overread first, then read the remaining bytes.
30
1.39M
    if (unlikely(Sec.getContentSize() < ReadSize)) {
31
56
      return logLoadError(ErrCode::Value::UnexpectedEnd, FMgr.getLastOffset(),
32
56
                          ASTNodeAttr::Sec_Custom);
33
56
    }
34
1.39M
    EXPECTED_TRY(
35
1.39M
        std::vector<uint8_t> Bytes,
36
1.39M
        FMgr.readBytes(Sec.getContentSize() - ReadSize).map_error(ReportError));
37
1.39M
    Sec.getContent().insert(Sec.getContent().end(), Bytes.begin(), Bytes.end());
38
1.39M
    return {};
39
1.39M
  });
40
1.39M
}
41
42
// Load vector of type section. See "include/loader/loader.h".
43
6.43k
Expect<void> Loader::loadSection(AST::TypeSection &Sec) {
44
6.43k
  return loadSectionContent(Sec, [this, &Sec]() -> Expect<void> {
45
6.39k
    auto ReportError = [this](auto E) {
46
91
      return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Sec_Type);
47
91
    };
48
49
    // Read the recursive type vector size.
50
6.39k
    EXPECTED_TRY(uint32_t VecCnt, loadVecCnt().map_error(ReportError));
51
    // Read the recursive types.
52
6.34k
    Sec.getContent().clear();
53
6.34k
    uint32_t SubTypeCnt = 0;
54
19.0k
    for (uint32_t I = 0; I < VecCnt; I++) {
55
13.0k
      EXPECTED_TRY(uint8_t CodeByte, FMgr.peekByte().map_error(ReportError));
56
57
13.0k
      TypeCode Code = static_cast<TypeCode>(CodeByte);
58
13.0k
      if (!Conf.hasProposal(Proposal::GC) && Code != TypeCode::Func) {
59
0
        return logNeedProposal(ErrCode::Value::IntegerTooLong, Proposal::GC,
60
0
                               FMgr.getOffset(), ASTNodeAttr::Sec_Type);
61
0
      }
62
13.0k
      if (Code == TypeCode::Rec) {
63
        // Case: 0x4E vec(subtype).
64
538
        FMgr.readByte();
65
538
        EXPECTED_TRY(uint32_t RecVecCnt, loadVecCnt().map_error(ReportError));
66
3.01k
        for (uint32_t J = 0; J < RecVecCnt; ++J) {
67
2.57k
          Sec.getContent().emplace_back();
68
2.57k
          EXPECTED_TRY(loadType(Sec.getContent().back()).map_error([](auto E) {
69
2.50k
            spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Sec_Type));
70
2.50k
            return E;
71
2.50k
          }));
72
2.50k
          Sec.getContent().back().setRecursiveInfo(J, RecVecCnt);
73
2.50k
          Sec.getContent().back().setTypeIndex(SubTypeCnt);
74
2.50k
          SubTypeCnt++;
75
2.50k
        }
76
12.5k
      } else {
77
        // Case: subtype.
78
12.5k
        Sec.getContent().emplace_back();
79
12.5k
        Sec.getContent().back().setTypeIndex(SubTypeCnt);
80
12.5k
        SubTypeCnt++;
81
12.5k
        EXPECTED_TRY(loadType(Sec.getContent().back()).map_error([](auto E) {
82
12.5k
          spdlog::error(ErrInfo::InfoAST(ASTNodeAttr::Sec_Type));
83
12.5k
          return E;
84
12.5k
        }));
85
12.5k
      }
86
13.0k
    }
87
5.99k
    return {};
88
6.34k
  });
89
6.43k
}
90
91
// Load vector of import section. See "include/loader/loader.h".
92
1.39k
Expect<void> Loader::loadSection(AST::ImportSection &Sec) {
93
1.39k
  return loadSectionContent(Sec, [this, &Sec]() {
94
1.33k
    return loadSectionContentVec(
95
18.3k
        Sec, [this](AST::ImportDesc &ImpDesc) { return loadDesc(ImpDesc); });
96
1.33k
  });
97
1.39k
}
98
99
// Load vector of function section. See "include/loader/loader.h".
100
5.30k
Expect<void> Loader::loadSection(AST::FunctionSection &Sec) {
101
5.30k
  return loadSectionContent(Sec, [this, &Sec]() {
102
5.25k
    return loadSectionContentVec(
103
158k
        Sec, [this](uint32_t &FuncIdx) -> Expect<void> {
104
158k
          EXPECTED_TRY(uint32_t Idx, FMgr.readU32().map_error([this](auto E) {
105
158k
            return logLoadError(E, FMgr.getLastOffset(),
106
158k
                                ASTNodeAttr::Sec_Function);
107
158k
          }));
108
158k
          FuncIdx = Idx;
109
158k
          return {};
110
158k
        });
111
5.25k
  });
112
5.30k
}
113
114
// Load vector of table section. See "include/loader/loader.h".
115
1.26k
Expect<void> Loader::loadSection(AST::TableSection &Sec) {
116
1.26k
  return loadSectionContent(Sec, [this, &Sec]() {
117
1.22k
    return loadSectionContentVec(
118
2.50k
        Sec, [this](AST::TableSegment &TabSeg) { return loadSegment(TabSeg); });
119
1.22k
  });
120
1.26k
}
121
122
// Load vector of memory section. See "include/loader/loader.h".
123
1.71k
Expect<void> Loader::loadSection(AST::MemorySection &Sec) {
124
1.71k
  return loadSectionContent(Sec, [this, &Sec]() {
125
1.68k
    return loadSectionContentVec(
126
3.80k
        Sec, [this](AST::MemoryType &MemType) { return loadType(MemType); });
127
1.68k
  });
128
1.71k
}
129
130
// Load vector of global section. See "include/loader/loader.h".
131
2.31k
Expect<void> Loader::loadSection(AST::GlobalSection &Sec) {
132
2.31k
  return loadSectionContent(Sec, [this, &Sec]() {
133
2.59k
    return loadSectionContentVec(Sec, [this](AST::GlobalSegment &GlobSeg) {
134
2.59k
      return loadSegment(GlobSeg);
135
2.59k
    });
136
2.27k
  });
137
2.31k
}
138
139
// Load vector of export section. See "include/loader/loader.h".
140
1.48k
Expect<void> Loader::loadSection(AST::ExportSection &Sec) {
141
1.48k
  return loadSectionContent(Sec, [this, &Sec]() {
142
1.43k
    return loadSectionContentVec(
143
19.8k
        Sec, [this](AST::ExportDesc &ExpDesc) { return loadDesc(ExpDesc); });
144
1.43k
  });
145
1.48k
}
146
147
// Load start function index. See "include/loader/loader.h".
148
205
Expect<void> Loader::loadSection(AST::StartSection &Sec) {
149
205
  return loadSectionContent(Sec, [this, &Sec]() -> Expect<void> {
150
    // Read u32 of start function index.
151
165
    EXPECTED_TRY(uint32_t Idx, FMgr.readU32().map_error([this](auto E) {
152
158
      return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Sec_Start);
153
158
    }));
154
158
    Sec.setContent(Idx);
155
158
    return {};
156
165
  });
157
205
}
158
159
// Load vector of element section. See "include/loader/loader.h".
160
3.85k
Expect<void> Loader::loadSection(AST::ElementSection &Sec) {
161
3.85k
  return loadSectionContent(Sec, [this, &Sec]() {
162
15.0k
    return loadSectionContentVec(Sec, [this](AST::ElementSegment &ElemSeg) {
163
15.0k
      return loadSegment(ElemSeg);
164
15.0k
    });
165
3.82k
  });
166
3.85k
}
167
168
// Load vector of code section. See "include/loader/loader.h".
169
5.66k
Expect<void> Loader::loadSection(AST::CodeSection &Sec) {
170
5.66k
  return loadSectionContent(Sec, [this, &Sec]() {
171
21.1k
    return loadSectionContentVec(Sec, [this](AST::CodeSegment &CodeSeg) {
172
21.1k
      return loadSegment(CodeSeg);
173
21.1k
    });
174
5.62k
  });
175
5.66k
}
176
177
// Load vector of data section. See "include/loader/loader.h".
178
3.20k
Expect<void> Loader::loadSection(AST::DataSection &Sec) {
179
3.20k
  return loadSectionContent(Sec, [this, &Sec]() {
180
7.68k
    return loadSectionContentVec(Sec, [this](AST::DataSegment &DataSeg) {
181
7.68k
      return loadSegment(DataSeg);
182
7.68k
    });
183
3.15k
  });
184
3.20k
}
185
186
// Load content of data count section. See "include/loader/loader.h".
187
392
Expect<void> Loader::loadSection(AST::DataCountSection &Sec) {
188
392
  return loadSectionContent(Sec, [this, &Sec]() -> Expect<void> {
189
    // Read u32 of data count.
190
347
    EXPECTED_TRY(uint32_t Cnt, FMgr.readU32().map_error([this](auto E) {
191
342
      return logLoadError(E, FMgr.getLastOffset(), ASTNodeAttr::Sec_DataCount);
192
342
    }));
193
342
    Sec.setContent(Cnt);
194
342
    return {};
195
347
  });
196
392
}
197
198
// Load content of tag section. See "include/loader/loader.h".
199
247
Expect<void> Loader::loadSection(AST::TagSection &Sec) {
200
247
  return loadSectionContent(Sec, [this, &Sec]() {
201
207
    return loadSectionContentVec(
202
3.34k
        Sec, [this](AST::TagType &TgType) { return loadType(TgType); });
203
207
  });
204
247
}
205
206
namespace {
207
208
0
inline constexpr uint32_t HostVersion() noexcept {
209
0
  return WasmEdge::AOT::kBinaryVersion;
210
0
}
211
212
0
inline constexpr uint8_t HostOSType() noexcept {
213
0
#if WASMEDGE_OS_LINUX
214
0
  return UINT8_C(1);
215
#elif WASMEDGE_OS_MACOS
216
  return UINT8_C(2);
217
#elif WASMEDGE_OS_WINDOWS
218
  return UINT8_C(3);
219
#else
220
  // Means WasmEdge is not yet supported on this OS.
221
  return UINT8_C(-1);
222
#endif
223
0
}
224
225
0
inline constexpr uint8_t HostArchType() noexcept {
226
0
#if defined(__x86_64__) || defined(_M_X64)
227
0
  return UINT8_C(1);
228
#elif defined(__aarch64__)
229
  return UINT8_C(2);
230
#elif defined(__riscv) && __riscv_xlen == 64
231
  return UINT8_C(3);
232
#elif defined(__arm__) && __ARM_ARCH == 7
233
  return UINT8_C(4);
234
#elif defined(__s390x__)
235
  return UINT8_C(5);
236
#else
237
  // Means universal wasm binary is not yet supported on this arch.
238
  return UINT8_C(-1);
239
#endif
240
0
}
241
242
} // namespace
243
244
// If any loader error occurs in loadSection, fall back to interpreter mode with
245
// an info-level log.
246
0
Expect<void> Loader::loadSection(FileMgr &VecMgr, AST::AOTSection &Sec) {
247
0
  EXPECTED_TRY(auto Version, VecMgr.readU32().map_error([](auto E) {
248
0
    spdlog::error(E);
249
0
    spdlog::error("    AOT binary version read error:{}"sv, E);
250
0
    return E;
251
0
  }));
252
0
  Sec.setVersion(Version);
253
0
  if (unlikely(Sec.getVersion() != HostVersion())) {
254
0
    spdlog::error(ErrCode::Value::MalformedSection);
255
0
    spdlog::error("    AOT binary version unmatched."sv);
256
0
    return Unexpect(ErrCode::Value::MalformedSection);
257
0
  }
258
259
0
  EXPECTED_TRY(auto OSType, VecMgr.readByte().map_error([](auto E) {
260
0
    spdlog::error(E);
261
0
    spdlog::error("    AOT os type read error:{}"sv, E);
262
0
    return E;
263
0
  }));
264
0
  Sec.setOSType(OSType);
265
0
  if (unlikely(Sec.getOSType() != HostOSType())) {
266
0
    spdlog::error(ErrCode::Value::MalformedSection);
267
0
    spdlog::error("    AOT OS type unmatched."sv);
268
0
    return Unexpect(ErrCode::Value::MalformedSection);
269
0
  }
270
271
0
  EXPECTED_TRY(auto ArchType, VecMgr.readByte().map_error([](auto E) {
272
0
    spdlog::error(E);
273
0
    spdlog::error("    AOT arch type read error:{}"sv, E);
274
0
    return E;
275
0
  }));
276
0
  Sec.setArchType(ArchType);
277
0
  if (unlikely(Sec.getArchType() != HostArchType())) {
278
0
    spdlog::error(ErrCode::Value::MalformedSection);
279
0
    spdlog::error("    AOT arch type unmatched."sv);
280
0
    return Unexpect(ErrCode::Value::MalformedSection);
281
0
  }
282
283
0
  EXPECTED_TRY(auto VersionAddress, VecMgr.readU64().map_error([](auto E) {
284
0
    spdlog::error(E);
285
0
    spdlog::error("    AOT version address read error:{}"sv, E);
286
0
    return E;
287
0
  }));
288
0
  Sec.setVersionAddress(VersionAddress);
289
290
0
  EXPECTED_TRY(auto IntrinsicsAddress, VecMgr.readU64().map_error([](auto E) {
291
0
    spdlog::error(E);
292
0
    spdlog::error("    AOT intrinsics address read error:{}"sv, E);
293
0
    return E;
294
0
  }));
295
0
  Sec.setIntrinsicsAddress(IntrinsicsAddress);
296
297
0
  EXPECTED_TRY(auto TypesSize, VecMgr.readU64().map_error([](auto E) {
298
0
    spdlog::error(E);
299
0
    spdlog::error("    AOT types size read error:{}"sv, E);
300
0
    return E;
301
0
  }));
302
0
  if (TypesSize > VecMgr.getRemainSize()) {
303
0
    spdlog::error(ErrCode::Value::IntegerTooLong);
304
0
    spdlog::error("    AOT types size too large"sv);
305
0
    return Unexpect(ErrCode::Value::IntegerTooLong);
306
0
  }
307
0
  Sec.getTypesAddress().resize(TypesSize);
308
309
0
  for (size_t I = 0; I < Sec.getTypesAddress().size(); ++I) {
310
0
    EXPECTED_TRY(auto TypesAddress, VecMgr.readU64().map_error([](auto E) {
311
0
      spdlog::error(E);
312
0
      spdlog::error("    AOT type address read error:{}"sv, E);
313
0
      return E;
314
0
    }));
315
0
    Sec.getTypesAddress()[I] = TypesAddress;
316
0
  }
317
318
0
  EXPECTED_TRY(auto CodesSize, VecMgr.readU64().map_error([](auto E) {
319
0
    spdlog::error(E);
320
0
    spdlog::error("    AOT code size read error:{}"sv, E);
321
0
    return E;
322
0
  }));
323
0
  if (CodesSize > VecMgr.getRemainSize()) {
324
0
    spdlog::error(ErrCode::Value::IntegerTooLong);
325
0
    spdlog::error("    AOT code size too large"sv);
326
0
    return Unexpect(ErrCode::Value::IntegerTooLong);
327
0
  }
328
0
  Sec.getCodesAddress().resize(CodesSize);
329
330
0
  for (size_t I = 0; I < Sec.getCodesAddress().size(); ++I) {
331
0
    EXPECTED_TRY(auto CodesAddress, VecMgr.readU64().map_error([](auto E) {
332
0
      spdlog::error(E);
333
0
      spdlog::error("    AOT code address read error:{}"sv, E);
334
0
      return E;
335
0
    }));
336
0
    Sec.getCodesAddress()[I] = CodesAddress;
337
0
  }
338
339
0
  EXPECTED_TRY(auto SectionsSize, VecMgr.readU32().map_error([](auto E) {
340
0
    spdlog::error(E);
341
0
    spdlog::error("    AOT section count read error:{}"sv, E);
342
0
    return E;
343
0
  }));
344
0
  if (SectionsSize > VecMgr.getRemainSize()) {
345
0
    spdlog::error(ErrCode::Value::IntegerTooLong);
346
0
    spdlog::error("    AOT section count too large"sv);
347
0
    return Unexpect(ErrCode::Value::IntegerTooLong);
348
0
  }
349
0
  Sec.getSections().resize(SectionsSize);
350
351
0
  for (auto &Section : Sec.getSections()) {
352
0
    EXPECTED_TRY(std::get<0>(Section), VecMgr.readByte().map_error([](auto E) {
353
0
      spdlog::error(E);
354
0
      spdlog::error("    AOT section type read error:{}"sv, E);
355
0
      return E;
356
0
    }));
357
0
    EXPECTED_TRY(std::get<1>(Section), VecMgr.readU64().map_error([](auto E) {
358
0
      spdlog::error(E);
359
0
      spdlog::error("    AOT section offset read error:{}"sv, E);
360
0
      return E;
361
0
    }));
362
0
    EXPECTED_TRY(std::get<2>(Section), VecMgr.readU64().map_error([](auto E) {
363
0
      spdlog::error(E);
364
0
      spdlog::error("    AOT section size read error:{}"sv, E);
365
0
      return E;
366
0
    }));
367
0
    EXPECTED_TRY(uint32_t Size, VecMgr.readU32().map_error([](auto E) {
368
0
      spdlog::error(E);
369
0
      spdlog::error("    AOT section data size read error:{}"sv, E);
370
0
      return E;
371
0
    }));
372
0
    if (Size > VecMgr.getRemainSize()) {
373
0
      spdlog::error(ErrCode::Value::IntegerTooLong);
374
0
      spdlog::error("    AOT section data size is too large"sv);
375
0
      return Unexpect(ErrCode::Value::IntegerTooLong);
376
0
    }
377
0
    if (std::get<2>(Section) < Size) {
378
0
      spdlog::error(ErrCode::Value::IntegerTooLong);
379
0
      spdlog::error("    AOT section data size is larger then section size"sv);
380
0
      return Unexpect(ErrCode::Value::IntegerTooLong);
381
0
    }
382
0
    EXPECTED_TRY(auto Data, VecMgr.readBytes(Size).map_error([](auto E) {
383
0
      spdlog::error(E);
384
0
      spdlog::error("    AOT section data read error:{}"sv, E);
385
0
      return E;
386
0
    }));
387
0
    std::get<3>(Section) = std::move(Data);
388
0
  }
389
0
  return {};
390
0
}
391
392
} // namespace Loader
393
} // namespace WasmEdge