WasmBinaryReader.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "WasmReaderPch.h"
  6. #ifdef ENABLE_WASM
  7. #include "WasmLimits.h"
  8. #if ENABLE_DEBUG_CONFIG_OPTIONS
  9. #include "Codex/Utf8Helper.h"
  10. #endif
  11. namespace Wasm
  12. {
  13. WasmBinaryReader::WasmBinaryReader(ArenaAllocator* alloc, Js::WebAssemblyModule* module, const byte* source, size_t length) :
  14. m_alloc(alloc),
  15. m_start(source),
  16. m_end(source + length),
  17. m_pc(source),
  18. m_curFuncEnd(nullptr),
  19. m_currentSection(),
  20. m_readerState(READER_STATE_UNKNOWN),
  21. m_module(module)
  22. #if DBG_DUMP
  23. , m_ops(nullptr)
  24. #endif
  25. {
  26. m_currentSection.code = bSectLimit;
  27. #if DBG_DUMP
  28. m_ops = Anew(m_alloc, OpSet, m_alloc);
  29. #endif
  30. }
  31. void WasmBinaryReader::InitializeReader()
  32. {
  33. ValidateModuleHeader();
  34. m_readerState = READER_STATE_UNKNOWN;
  35. }
  36. void WasmBinaryReader::ThrowDecodingError(const char16* msg, ...) const
  37. {
  38. va_list argptr;
  39. va_start(argptr, msg);
  40. throw WasmCompilationException(msg, argptr);
  41. }
  42. SectionHeader WasmBinaryReader::ReadNextSection()
  43. {
  44. while (true)
  45. {
  46. if (EndOfModule())
  47. {
  48. memset(&m_currentSection, 0, sizeof(SectionHeader));
  49. m_currentSection.code = bSectLimit;
  50. return m_currentSection;
  51. }
  52. m_currentSection = ReadSectionHeader();
  53. if (SectionInfo::All[m_currentSection.code].flag == fSectIgnore)
  54. {
  55. TRACE_WASM_SECTION(_u("Ignore this section"));
  56. m_pc = m_currentSection.end;
  57. // Read next section
  58. continue;
  59. }
  60. return m_currentSection;
  61. }
  62. }
  63. bool WasmBinaryReader::ProcessCurrentSection()
  64. {
  65. Assert(m_currentSection.code != bSectLimit);
  66. TRACE_WASM_SECTION(_u("Process section %s"), SectionInfo::All[m_currentSection.code].name);
  67. m_readerState = READER_STATE_MODULE;
  68. switch (m_currentSection.code)
  69. {
  70. case bSectMemory:
  71. ReadMemorySection(false);
  72. break;
  73. case bSectType:
  74. ReadSignatureTypeSection();
  75. break;
  76. case bSectImport:
  77. ReadImportSection();
  78. break;
  79. case bSectFunction:
  80. ReadFunctionSignatures();
  81. break;
  82. case bSectFunctionBodies:
  83. ReadFunctionHeaders();
  84. break;
  85. case bSectExport:
  86. ReadExportSection();
  87. break;
  88. case bSectStartFunction:
  89. ReadStartFunction();
  90. break;
  91. case bSectData:
  92. ReadDataSection();
  93. break;
  94. case bSectTable:
  95. ReadTableSection(false);
  96. break;
  97. case bSectElement:
  98. ReadElementSection();
  99. break;
  100. case bSectName:
  101. ReadNameSection();
  102. break;
  103. case bSectGlobal:
  104. ReadGlobalSection();
  105. break;
  106. case bSectCustom:
  107. ReadCustomSection();
  108. break;
  109. default:
  110. Assert(UNREACHED);
  111. m_readerState = READER_STATE_UNKNOWN;
  112. return false;
  113. }
  114. m_readerState = READER_STATE_UNKNOWN;
  115. return m_pc == m_currentSection.end;
  116. }
  117. SectionHeader WasmBinaryReader::ReadSectionHeader()
  118. {
  119. SectionHeader header;
  120. header.start = m_pc;
  121. header.code = bSectLimit;
  122. uint32 len = 0;
  123. CompileAssert(sizeof(SectionCode) == sizeof(uint8));
  124. SectionCode sectionId = (SectionCode)LEB128<uint8, 7>(len);
  125. if (sectionId > bsectLastKnownSection)
  126. {
  127. ThrowDecodingError(_u("Invalid known section opcode %u"), sectionId);
  128. }
  129. uint32 sectionSize = LEB128(len);
  130. header.end = m_pc + sectionSize;
  131. CheckBytesLeft(sectionSize);
  132. header.code = sectionId;
  133. if (sectionId == bSectCustom)
  134. {
  135. header.name = ReadInlineName(len, header.nameLength);
  136. }
  137. else
  138. {
  139. header.name = SectionInfo::All[sectionId].name;
  140. header.nameLength = SectionInfo::All[sectionId].nameLength;
  141. }
  142. TRACE_WASM_SECTION(_u("Section Header: %s, length = %u (0x%x)"), header.name, sectionSize, sectionSize);
  143. return header;
  144. }
  145. #if ENABLE_DEBUG_CONFIG_OPTIONS
  146. Js::FunctionBody* WasmBinaryReader::GetFunctionBody() const
  147. {
  148. if (m_readerState == READER_STATE_FUNCTION)
  149. {
  150. return m_funcState.body;
  151. }
  152. return nullptr;
  153. }
  154. #endif
  155. #if DBG_DUMP
  156. void WasmBinaryReader::PrintOps()
  157. {
  158. int count = m_ops->Count();
  159. if (count == 0)
  160. {
  161. return;
  162. }
  163. WasmOp* ops = HeapNewArray(WasmOp, count);
  164. auto iter = m_ops->GetIterator();
  165. int i = 0;
  166. while (iter.IsValid())
  167. {
  168. __analysis_assume(i < count);
  169. ops[i] = iter.CurrentKey();
  170. iter.MoveNext();
  171. ++i;
  172. }
  173. for (i = 0; i < count; ++i)
  174. {
  175. int j = i;
  176. while (j > 0 && ops[j-1] > ops[j])
  177. {
  178. WasmOp tmp = ops[j];
  179. ops[j] = ops[j - 1];
  180. ops[j - 1] = tmp;
  181. --j;
  182. }
  183. }
  184. uint32 moduleId = m_module->GetWasmFunctionInfo(0)->GetBody()->GetSourceContextId();
  185. Output::Print(_u("Module #%u's current opcode distribution\n"), moduleId);
  186. for (i = 0; i < count; ++i)
  187. {
  188. switch (ops[i])
  189. {
  190. #define WASM_OPCODE(opname, opcode, sig, imp, wat) \
  191. case opcode: \
  192. Output::Print(_u("%s: %s\r\n"), _u(#opname), _u(wat)); \
  193. break;
  194. #include "WasmBinaryOpCodes.h"
  195. }
  196. }
  197. HeapDeleteArray(count, ops);
  198. }
  199. #endif
  200. void WasmBinaryReader::ReadFunctionHeaders()
  201. {
  202. uint32 len;
  203. uint32 entries = LEB128(len);
  204. uint32 importCount = m_module->GetImportedFunctionCount();
  205. if (m_module->GetWasmFunctionCount() < importCount ||
  206. entries != m_module->GetWasmFunctionCount() - importCount)
  207. {
  208. ThrowDecodingError(_u("Function signatures and function bodies count mismatch"));
  209. }
  210. for (uint32 i = 0; i < entries; ++i)
  211. {
  212. uint32 funcIndex = i + importCount;
  213. WasmFunctionInfo* funcInfo = m_module->GetWasmFunctionInfo(funcIndex);
  214. const uint32 funcSize = LEB128(len);
  215. if (funcSize > Limits::GetMaxFunctionSize())
  216. {
  217. ThrowDecodingError(_u("Function body too big"));
  218. }
  219. funcInfo->SetReaderInfo(FunctionBodyReaderInfo(funcSize, (m_pc - m_start)));
  220. CheckBytesLeft(funcSize);
  221. TRACE_WASM_DECODER(_u("Function body header: index = %u, size = %u"), funcIndex, funcSize);
  222. const byte* end = m_pc + funcSize;
  223. m_pc = end;
  224. }
  225. }
  226. void WasmBinaryReader::SeekToFunctionBody(class WasmFunctionInfo* funcInfo)
  227. {
  228. FunctionBodyReaderInfo readerInfo = funcInfo->GetReaderInfo();
  229. if (m_end < m_start || readerInfo.startOffset >= (size_t)(m_end - m_start))
  230. {
  231. ThrowDecodingError(_u("Function byte offset out of bounds"));
  232. }
  233. if (m_readerState != READER_STATE_UNKNOWN)
  234. {
  235. ThrowDecodingError(_u("Wasm reader in an invalid state to read function code"));
  236. }
  237. m_readerState = READER_STATE_FUNCTION;
  238. // Seek to the function start and skip function header (count)
  239. m_pc = m_start + readerInfo.startOffset;
  240. m_funcState.size = readerInfo.size;
  241. m_funcState.count = 0;
  242. CheckBytesLeft(readerInfo.size);
  243. m_curFuncEnd = m_pc + m_funcState.size;
  244. #if ENABLE_DEBUG_CONFIG_OPTIONS
  245. m_funcState.body = funcInfo->GetBody();
  246. if (DO_WASM_TRACE_DECODER)
  247. {
  248. Output::Print(_u("Decoding "));
  249. m_funcState.body->DumpFullFunctionName();
  250. if (sizeof(intptr_t) == 8)
  251. {
  252. Output::Print(_u(": start = 0x%llx, end = 0x%llx, size = 0x%x\n"), (intptr_t)m_pc, (intptr_t)m_curFuncEnd, m_funcState.size);
  253. }
  254. else
  255. {
  256. Output::Print(_u(": start = 0x%x, end = 0x%x, size = 0x%x\n"), (intptr_t)m_pc, (intptr_t)m_curFuncEnd, m_funcState.size);
  257. }
  258. }
  259. #endif
  260. uint32 length = 0;
  261. uint32 numLocalsEntries = LEB128(length);
  262. m_funcState.count += length;
  263. // locals
  264. for (uint32 j = 0; j < numLocalsEntries; j++)
  265. {
  266. uint32 numLocals = LEB128(length);
  267. m_funcState.count += length;
  268. WasmTypes::WasmType type = ReadWasmType(length);
  269. if (!WasmTypes::IsLocalType(type))
  270. {
  271. ThrowDecodingError(_u("Invalid local type"));
  272. }
  273. m_funcState.count += length;
  274. uint32 totalLocals = 0;
  275. if (UInt32Math::Add(funcInfo->GetLocalCount(), numLocals, &totalLocals) || totalLocals > Limits::GetMaxFunctionLocals())
  276. {
  277. ThrowDecodingError(_u("Too many locals"));
  278. }
  279. funcInfo->AddLocal(type, numLocals);
  280. TRACE_WASM_DECODER(_u("Local: type = %s, count = %u"), WasmTypes::GetTypeName(type), numLocals);
  281. }
  282. }
  283. void WasmBinaryReader::FunctionEnd()
  284. {
  285. m_readerState = READER_STATE_UNKNOWN;
  286. #if ENABLE_DEBUG_CONFIG_OPTIONS
  287. m_funcState.body = nullptr;
  288. #endif
  289. }
  290. bool WasmBinaryReader::IsCurrentFunctionCompleted() const
  291. {
  292. return m_pc == m_curFuncEnd;
  293. }
  294. const uint32 WasmBinaryReader::EstimateCurrentFunctionBytecodeSize() const
  295. {
  296. if (m_readerState != READER_STATE_FUNCTION)
  297. {
  298. ThrowDecodingError(_u("Wasm reader in an invalid state to get function information"));
  299. }
  300. // Use binary size to estimate bytecode size
  301. return m_funcState.size;
  302. }
  303. WasmOp WasmBinaryReader::ReadPrefixedOpCode(WasmOp prefix, bool isSupported, const char16* notSupportedMsg)
  304. {
  305. CompileAssert(sizeof(WasmOp) >= 2);
  306. if (!isSupported)
  307. {
  308. ThrowDecodingError(notSupportedMsg);
  309. }
  310. CheckBytesLeft(1);
  311. ++m_funcState.count;
  312. return (WasmOp)((prefix << 8) | (*m_pc++));
  313. }
  314. WasmOp WasmBinaryReader::ReadOpCode()
  315. {
  316. CheckBytesLeft(1);
  317. WasmOp op = (WasmOp)*m_pc++;
  318. ++m_funcState.count;
  319. switch (op)
  320. {
  321. #define WASM_PREFIX(name, value, imp, errorMsg) \
  322. case prefix##name: \
  323. return ReadPrefixedOpCode(op, imp, _u(errorMsg));
  324. #include "WasmBinaryOpCodes.h"
  325. }
  326. return op;
  327. }
  328. WasmOp WasmBinaryReader::ReadExpr()
  329. {
  330. WasmOp op = m_currentNode.op = ReadOpCode();
  331. if (EndOfFunc())
  332. {
  333. // end of AST
  334. if (op != wbEnd)
  335. {
  336. ThrowDecodingError(_u("missing function end opcode"));
  337. }
  338. return op;
  339. }
  340. switch (op)
  341. {
  342. case wbBlock:
  343. case wbLoop:
  344. case wbIf:
  345. BlockNode();
  346. break;
  347. case wbElse:
  348. // no node attributes
  349. break;
  350. case wbCall:
  351. CallNode();
  352. break;
  353. case wbCallIndirect:
  354. CallIndirectNode();
  355. break;
  356. case wbBr:
  357. case wbBrIf:
  358. BrNode();
  359. break;
  360. case wbBrTable:
  361. BrTableNode();
  362. break;
  363. case wbReturn:
  364. break;
  365. case wbI32Const:
  366. ConstNode<WasmTypes::I32>();
  367. break;
  368. case wbI64Const:
  369. ConstNode<WasmTypes::I64>();
  370. break;
  371. case wbF32Const:
  372. ConstNode<WasmTypes::F32>();
  373. break;
  374. case wbF64Const:
  375. ConstNode<WasmTypes::F64>();
  376. break;
  377. #ifdef ENABLE_WASM_SIMD
  378. case wbM128Const:
  379. ConstNode<WasmTypes::M128>();
  380. break;
  381. #endif
  382. case wbSetLocal:
  383. case wbGetLocal:
  384. case wbTeeLocal:
  385. case wbGetGlobal:
  386. case wbSetGlobal:
  387. VarNode();
  388. break;
  389. case wbDrop:
  390. break;
  391. case wbEnd:
  392. break;
  393. case wbNop:
  394. break;
  395. case wbMemorySize:
  396. case wbMemoryGrow:
  397. {
  398. // Reserved value currently unused
  399. uint8 reserved = ReadConst<uint8>();
  400. if (reserved != 0)
  401. {
  402. ThrowDecodingError(op == wbMemorySize
  403. ? _u("memory.size reserved value must be 0")
  404. : _u("memory.grow reserved value must be 0")
  405. );
  406. }
  407. break;
  408. }
  409. #ifdef ENABLE_WASM_SIMD
  410. case wbV8X16Shuffle:
  411. ShuffleNode();
  412. break;
  413. #define WASM_LANE_OPCODE(opname, ...) \
  414. case wb##opname: \
  415. LaneNode(); \
  416. break;
  417. #endif
  418. #define WASM_MEM_OPCODE(opname, ...) \
  419. case wb##opname: \
  420. MemNode(); \
  421. break;
  422. #include "WasmBinaryOpCodes.h"
  423. default:
  424. break;
  425. }
  426. #if DBG_DUMP
  427. m_ops->AddNew(op);
  428. #endif
  429. return op;
  430. }
  431. void WasmBinaryReader::ValidateModuleHeader()
  432. {
  433. uint32 bytesLeft = (uint32)(m_end - m_pc);
  434. if (bytesLeft > Limits::GetMaxModuleSize())
  435. {
  436. ThrowDecodingError(_u("Module too big"));
  437. }
  438. uint32 magicNumber = ReadConst<uint32>();
  439. uint32 version = ReadConst<uint32>();
  440. TRACE_WASM_DECODER(_u("Module Header: Magic 0x%x, Version %u"), magicNumber, version);
  441. if (magicNumber != 0x6d736100)
  442. {
  443. ThrowDecodingError(_u("Malformed WASM module header!"));
  444. }
  445. if (CONFIG_FLAG(WasmCheckVersion))
  446. {
  447. if (version != binaryVersion)
  448. {
  449. ThrowDecodingError(_u("Invalid WASM version!"));
  450. }
  451. }
  452. }
  453. void WasmBinaryReader::CallNode()
  454. {
  455. uint32 length = 0;
  456. uint32 funcNum = LEB128(length);
  457. m_funcState.count += length;
  458. FunctionIndexTypes::Type funcType = m_module->GetFunctionIndexType(funcNum);
  459. if (funcType == FunctionIndexTypes::Invalid)
  460. {
  461. ThrowDecodingError(_u("Function is out of bound"));
  462. }
  463. m_currentNode.call.funcType = funcType;
  464. m_currentNode.call.num = funcNum;
  465. }
  466. void WasmBinaryReader::CallIndirectNode()
  467. {
  468. uint32 length = 0;
  469. uint32 funcNum = LEB128(length);
  470. // Reserved value currently unused
  471. uint8 reserved = ReadConst<uint8>();
  472. if (reserved != 0)
  473. {
  474. ThrowDecodingError(_u("call_indirect reserved value must be 0"));
  475. }
  476. if (!m_module->HasTable() && !m_module->HasTableImport())
  477. {
  478. ThrowDecodingError(_u("Found call_indirect operator, but no table"));
  479. }
  480. m_funcState.count += length;
  481. if (funcNum >= m_module->GetSignatureCount())
  482. {
  483. ThrowDecodingError(_u("Function is out of bound"));
  484. }
  485. m_currentNode.call.num = funcNum;
  486. m_currentNode.call.funcType = FunctionIndexTypes::Function;
  487. }
  488. void WasmBinaryReader::BlockNode()
  489. {
  490. uint32 len = 0;
  491. int64 blocktype = SLEB128<int64, 33>(len);
  492. m_funcState.count += len;
  493. // Negative values means it's a value type or Void
  494. if (blocktype < 0)
  495. {
  496. // Only support 1 byte for negative values
  497. if (len != 1)
  498. {
  499. ThrowDecodingError(_u("Invalid blocktype %lld"), blocktype);
  500. }
  501. int8 blockSig = (int8)blocktype;
  502. // Check if it's an empty block
  503. if (blockSig == LanguageTypes::emptyBlock)
  504. {
  505. m_currentNode.block.SetSingleResult(WasmTypes::Void);
  506. }
  507. else
  508. {
  509. // Otherwise, it should be a value type
  510. WasmTypes::WasmType type = LanguageTypes::ToWasmType(blockSig);
  511. m_currentNode.block.SetSingleResult(type);
  512. }
  513. }
  514. else
  515. {
  516. // Positive values means it a function signature
  517. // Function signature is only supported with the Multi-Value feature
  518. if (!CONFIG_FLAG(WasmMultiValue))
  519. {
  520. ThrowDecodingError(_u("Block signature not supported"));
  521. }
  522. // Make sure the blocktype is a u32 after checking for negative values
  523. if (blocktype > UINT32_MAX)
  524. {
  525. ThrowDecodingError(_u("Invalid blocktype %lld"), blocktype);
  526. }
  527. uint32 blockId = (uint32)blocktype;
  528. if (!m_module->IsSignatureIndexValid(blockId))
  529. {
  530. ThrowDecodingError(_u("Block signature %u is invalid"), blockId);
  531. }
  532. m_currentNode.block.SetSignatureId(blockId);
  533. }
  534. }
  535. // control flow
  536. void WasmBinaryReader::BrNode()
  537. {
  538. uint32 len = 0;
  539. m_currentNode.br.depth = LEB128(len);
  540. m_funcState.count += len;
  541. }
  542. void WasmBinaryReader::BrTableNode()
  543. {
  544. uint32 len = 0;
  545. m_currentNode.brTable.numTargets = LEB128(len);
  546. if (m_currentNode.brTable.numTargets > Limits::GetMaxBrTableElems())
  547. {
  548. ThrowDecodingError(_u("br_table too big"));
  549. }
  550. m_funcState.count += len;
  551. m_currentNode.brTable.targetTable = AnewArray(m_alloc, uint32, m_currentNode.brTable.numTargets);
  552. for (uint32 i = 0; i < m_currentNode.brTable.numTargets; i++)
  553. {
  554. m_currentNode.brTable.targetTable[i] = LEB128(len);
  555. m_funcState.count += len;
  556. }
  557. m_currentNode.brTable.defaultTarget = LEB128(len);
  558. m_funcState.count += len;
  559. }
  560. void WasmBinaryReader::ShuffleNode()
  561. {
  562. CheckBytesLeft(Simd::MAX_LANES);
  563. for (uint32 i = 0; i < Simd::MAX_LANES; i++)
  564. {
  565. m_currentNode.shuffle.indices[i] = ReadConst<uint8>();
  566. }
  567. m_funcState.count += Simd::MAX_LANES;
  568. }
  569. void WasmBinaryReader::LaneNode()
  570. {
  571. m_currentNode.lane.index = ReadConst<uint8>();
  572. m_funcState.count++;
  573. }
  574. void WasmBinaryReader::MemNode()
  575. {
  576. uint32 len = 0;
  577. // flags
  578. const uint32 flags = LEB128(len);
  579. m_currentNode.mem.alignment = (uint8)flags;
  580. m_funcState.count += len;
  581. m_currentNode.mem.offset = LEB128(len);
  582. m_funcState.count += len;
  583. }
  584. // Locals/Globals
  585. void WasmBinaryReader::VarNode()
  586. {
  587. uint32 length;
  588. m_currentNode.var.num = LEB128(length);
  589. m_funcState.count += length;
  590. }
  591. // Const
  592. template <WasmTypes::WasmType localType>
  593. void WasmBinaryReader::ConstNode()
  594. {
  595. uint32 len = 0;
  596. switch (localType)
  597. {
  598. case WasmTypes::I32:
  599. m_currentNode.cnst.i32 = SLEB128(len);
  600. m_funcState.count += len;
  601. break;
  602. case WasmTypes::I64:
  603. m_currentNode.cnst.i64 = SLEB128<int64>(len);
  604. m_funcState.count += len;
  605. break;
  606. case WasmTypes::F32:
  607. {
  608. m_currentNode.cnst.i32 = ReadConst<int32>();
  609. CompileAssert(sizeof(int32) == sizeof(float));
  610. m_funcState.count += sizeof(float);
  611. break;
  612. }
  613. case WasmTypes::F64:
  614. m_currentNode.cnst.i64 = ReadConst<int64>();
  615. CompileAssert(sizeof(int64) == sizeof(double));
  616. m_funcState.count += sizeof(double);
  617. break;
  618. #ifdef ENABLE_WASM_SIMD
  619. case WasmTypes::M128:
  620. Simd::EnsureSimdIsEnabled();
  621. for (uint i = 0; i < Simd::VEC_WIDTH; i++)
  622. {
  623. m_currentNode.cnst.v128[i] = ReadConst<uint>();
  624. }
  625. m_funcState.count += Simd::VEC_WIDTH;
  626. break;
  627. #endif
  628. default:
  629. WasmTypes::CompileAssertCases<Wasm::WasmTypes::I32, Wasm::WasmTypes::I64, Wasm::WasmTypes::F32, Wasm::WasmTypes::F64, WASM_M128_CHECK_TYPE>();
  630. }
  631. }
  632. bool WasmBinaryReader::EndOfFunc()
  633. {
  634. return m_funcState.count >= m_funcState.size;
  635. }
  636. bool WasmBinaryReader::EndOfModule()
  637. {
  638. return (m_pc >= m_end);
  639. }
  640. void WasmBinaryReader::ReadMemorySection(bool isImportSection)
  641. {
  642. uint32 length = 0;
  643. uint32 count;
  644. if (isImportSection)
  645. {
  646. count = 1;
  647. }
  648. else
  649. {
  650. count = LEB128(length);
  651. }
  652. if (count > 1)
  653. {
  654. ThrowDecodingError(_u("Maximum of 1 memory allowed"));
  655. }
  656. if (count == 1)
  657. {
  658. MemorySectionLimits limits = ReadSectionLimitsBase<MemorySectionLimits>(Limits::GetMaxMemoryInitialPages(), Limits::GetMaxMemoryMaximumPages(), _u("memory size too big"));
  659. if (Wasm::Threads::IsEnabled() && limits.IsShared() && !limits.HasMaximum())
  660. {
  661. ThrowDecodingError(_u("Shared memory must have a maximum size"));
  662. }
  663. m_module->InitializeMemory(&limits);
  664. }
  665. }
  666. void WasmBinaryReader::ReadSignatureTypeSection()
  667. {
  668. uint32 len = 0;
  669. const uint32 numTypes = LEB128(len);
  670. if (numTypes > Limits::GetMaxTypes())
  671. {
  672. ThrowDecodingError(_u("Too many signatures"));
  673. }
  674. m_module->SetSignatureCount(numTypes);
  675. // signatures table
  676. for (uint32 i = 0; i < numTypes; i++)
  677. {
  678. WasmSignature* sig = m_module->GetSignature(i);
  679. sig->SetSignatureId(i);
  680. int8 form = SLEB128<int8, 7>(len);
  681. if (form != LanguageTypes::func)
  682. {
  683. ThrowDecodingError(_u("Unexpected type form 0x%X"), form);
  684. }
  685. uint32 paramCount32 = LEB128(len);
  686. if (paramCount32 > Limits::GetMaxFunctionParams() || paramCount32 > UINT16_MAX)
  687. {
  688. ThrowDecodingError(_u("Too many arguments in signature"));
  689. }
  690. Js::ArgSlot paramCount = (Js::ArgSlot)paramCount32;
  691. sig->AllocateParams(paramCount, m_module->GetRecycler());
  692. for (Js::ArgSlot j = 0; j < paramCount; j++)
  693. {
  694. WasmTypes::WasmType type = ReadWasmType(len);
  695. sig->SetParam(type, j);
  696. }
  697. uint32 resultCount = LEB128(len);
  698. if (resultCount > Limits::GetMaxFunctionReturns())
  699. {
  700. ThrowDecodingError(_u("Too many returns in signature: %u. Maximum allowed: %u"), resultCount, Limits::GetMaxFunctionReturns());
  701. }
  702. sig->AllocateResults(resultCount, m_module->GetRecycler());
  703. for (uint32 iResult = 0; iResult < resultCount; ++iResult)
  704. {
  705. WasmTypes::WasmType type = ReadWasmType(len);
  706. sig->SetResult(type, iResult);
  707. }
  708. sig->FinalizeSignature();
  709. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  710. if (DO_WASM_TRACE_DECODER)
  711. {
  712. Output::Print(_u("Signature #%u: "), i);
  713. sig->Dump();
  714. Output::Print(_u("\n"));
  715. }
  716. #endif
  717. }
  718. }
  719. void WasmBinaryReader::ReadFunctionSignatures()
  720. {
  721. uint32 len = 0;
  722. uint32 nFunctions = LEB128(len);
  723. uint32 totalFunctions = 0;
  724. if (UInt32Math::Add(nFunctions, m_module->GetWasmFunctionCount(), &totalFunctions) || totalFunctions > Limits::GetMaxFunctions())
  725. {
  726. ThrowDecodingError(_u("Too many functions"));
  727. }
  728. for (uint32 iFunc = 0; iFunc < nFunctions; iFunc++)
  729. {
  730. uint32 sigIndex = LEB128(len);
  731. if (sigIndex >= m_module->GetSignatureCount())
  732. {
  733. ThrowDecodingError(_u("Function signature is out of bound"));
  734. }
  735. WasmSignature* sig = m_module->GetSignature(sigIndex);
  736. m_module->AddWasmFunctionInfo(sig);
  737. }
  738. }
  739. void WasmBinaryReader::ReadExportSection()
  740. {
  741. uint32 length;
  742. uint32 numExports = LEB128(length);
  743. if (numExports > Limits::GetMaxExports())
  744. {
  745. ThrowDecodingError(_u("Too many exports"));
  746. }
  747. m_module->AllocateFunctionExports(numExports);
  748. ArenaAllocator tmpAlloc(_u("ExportDupCheck"), m_module->GetScriptContext()->GetThreadContext()->GetPageAllocator(), Js::Throw::OutOfMemory);
  749. typedef SList<const char16*> NameList;
  750. JsUtil::BaseDictionary<uint32, NameList*, ArenaAllocator> exportsNameDict(&tmpAlloc);
  751. for (uint32 iExport = 0; iExport < numExports; iExport++)
  752. {
  753. uint32 nameLength;
  754. const char16* exportName = ReadInlineName(length, nameLength);
  755. // Check if the name is already used
  756. NameList* list = nullptr;
  757. if (exportsNameDict.TryGetValue(nameLength, &list))
  758. {
  759. const char16** found = list->Find([exportName, nameLength](const char16* existing) {
  760. return wcsncmp(exportName, existing, nameLength) == 0;
  761. });
  762. if (found)
  763. {
  764. ThrowDecodingError(_u("Duplicate export name: %s"), exportName);
  765. }
  766. }
  767. else
  768. {
  769. list = Anew(&tmpAlloc, NameList, &tmpAlloc);
  770. exportsNameDict.Add(nameLength, list);
  771. }
  772. list->Push(exportName);
  773. ExternalKinds kind = ReadExternalKind();
  774. uint32 index = LEB128(length);
  775. switch (kind)
  776. {
  777. case ExternalKinds::Function:
  778. {
  779. FunctionIndexTypes::Type type = m_module->GetFunctionIndexType(index);
  780. if (!FunctionIndexTypes::CanBeExported(type))
  781. {
  782. ThrowDecodingError(_u("Invalid Export %u => func[%u]"), iExport, index);
  783. }
  784. m_module->SetExport(iExport, index, exportName, nameLength, kind);
  785. #if DBG_DUMP
  786. if (type == FunctionIndexTypes::ImportThunk)
  787. {
  788. WasmImport* import = m_module->GetWasmFunctionInfo(index)->importedFunctionReference;
  789. TRACE_WASM_DECODER(_u("Export #%u: Import(%s.%s)(%u) => %s"), iExport, import->modName, import->importName, index, exportName);
  790. }
  791. else
  792. {
  793. TRACE_WASM_DECODER(_u("Export #%u: Function(%u) => %s"), iExport, index, exportName);
  794. }
  795. #endif
  796. break;
  797. }
  798. case ExternalKinds::Memory:
  799. if (index != 0)
  800. {
  801. ThrowDecodingError(_u("Unknown memory index %u for export %s"), index, exportName);
  802. }
  803. m_module->SetExport(iExport, index, exportName, nameLength, kind);
  804. break;
  805. case ExternalKinds::Table:
  806. if (index != 0)
  807. {
  808. ThrowDecodingError(_u("Unknown table index %u for export %s"), index, exportName);
  809. }
  810. m_module->SetExport(iExport, index, exportName, nameLength, kind);
  811. break;
  812. case ExternalKinds::Global:
  813. if (index >= m_module->GetGlobalCount())
  814. {
  815. ThrowDecodingError(_u("Unknown global %u for export %s"), index, exportName);
  816. }
  817. if (m_module->GetGlobal(index)->IsMutable())
  818. {
  819. ThrowDecodingError(_u("Mutable globals cannot be exported"), index, exportName);
  820. }
  821. m_module->SetExport(iExport, index, exportName, nameLength, kind);
  822. break;
  823. default:
  824. ThrowDecodingError(_u("Exported Kind %d, NYI"), kind);
  825. break;
  826. }
  827. }
  828. }
  829. void WasmBinaryReader::ReadTableSection(bool isImportSection)
  830. {
  831. uint32 length;
  832. uint32 entries;
  833. if (isImportSection)
  834. {
  835. entries = 1;
  836. }
  837. else
  838. {
  839. entries = LEB128(length);
  840. }
  841. if (entries > 1)
  842. {
  843. ThrowDecodingError(_u("Maximum of one table allowed"));
  844. }
  845. if (entries == 1)
  846. {
  847. int8 elementType = SLEB128<int8, 7>(length);
  848. if (elementType != LanguageTypes::anyfunc)
  849. {
  850. ThrowDecodingError(_u("Only anyfunc type is supported. Unknown type %d"), elementType);
  851. }
  852. TableSectionLimits limits = ReadSectionLimitsBase<TableSectionLimits>(Limits::GetMaxTableSize(), Limits::GetMaxTableSize(), _u("table too big"));
  853. m_module->InitializeTable(&limits);
  854. TRACE_WASM_DECODER(_u("Indirect table: %u to %u entries"), limits.initial, limits.maximum);
  855. }
  856. }
  857. void WasmBinaryReader::ReadElementSection()
  858. {
  859. uint32 length = 0;
  860. uint32 numSegments = LEB128(length);
  861. if (numSegments > Limits::GetMaxElementSegments())
  862. {
  863. ThrowDecodingError(_u("Too many element segments"));
  864. }
  865. if (numSegments > 0)
  866. {
  867. m_module->AllocateElementSegs(numSegments);
  868. }
  869. TRACE_WASM_DECODER(_u("Indirect table element: %u entries"), numSegments);
  870. for (uint32 i = 0; i < numSegments; ++i)
  871. {
  872. uint32 index = LEB128(length); // Table id
  873. if (index != 0 || !(m_module->HasTable() || m_module->HasTableImport()))
  874. {
  875. ThrowDecodingError(_u("Unknown table index %d"), index); //MVP limitation
  876. }
  877. WasmNode initExpr = ReadInitExpr(true);
  878. uint32 numElem = LEB128(length);
  879. if (numElem > Limits::GetMaxTableSize())
  880. {
  881. ThrowDecodingError(_u("Too many table element"));
  882. }
  883. WasmElementSegment* eSeg = Anew(m_alloc, WasmElementSegment, m_alloc, index, initExpr, numElem);
  884. for (uint32 iElem = 0; iElem < numElem; ++iElem)
  885. {
  886. uint32 elem = LEB128(length);
  887. FunctionIndexTypes::Type funcType = m_module->GetFunctionIndexType(elem);
  888. if (!FunctionIndexTypes::CanBeExported(funcType))
  889. {
  890. ThrowDecodingError(_u("Invalid function to insert in the table %u"), elem);
  891. }
  892. eSeg->AddElement(elem);
  893. }
  894. m_module->SetElementSeg(eSeg, i);
  895. }
  896. }
  897. void WasmBinaryReader::ReadDataSection()
  898. {
  899. uint32 len = 0;
  900. const uint32 numSegments = LEB128(len);
  901. if (numSegments > Limits::GetMaxDataSegments())
  902. {
  903. ThrowDecodingError(_u("Too many data segments"));
  904. }
  905. if (numSegments > 0)
  906. {
  907. m_module->AllocateDataSegs(numSegments);
  908. }
  909. for (uint32 i = 0; i < numSegments; ++i)
  910. {
  911. uint32 index = LEB128(len);
  912. if (index != 0 || !(m_module->HasMemory() || m_module->HasMemoryImport()))
  913. {
  914. ThrowDecodingError(_u("Unknown memory index %u"), index);
  915. }
  916. TRACE_WASM_DECODER(_u("Data Segment #%u"), i);
  917. WasmNode initExpr = ReadInitExpr(true);
  918. uint32 dataByteLen = LEB128(len);
  919. WasmDataSegment* dseg = Anew(m_alloc, WasmDataSegment, m_alloc, initExpr, dataByteLen, m_pc);
  920. CheckBytesLeft(dataByteLen);
  921. m_pc += dataByteLen;
  922. m_module->SetDataSeg(dseg, i);
  923. }
  924. }
  925. void WasmBinaryReader::ReadNameSection()
  926. {
  927. uint32 len = 0;
  928. uint32 numFuncNames = LEB128(len);
  929. if (numFuncNames > Limits::GetMaxFunctions())
  930. {
  931. ThrowDecodingError(_u("Too many function names"));
  932. }
  933. for (uint32 i = 0; i < numFuncNames; ++i)
  934. {
  935. uint32 fnNameLen = 0;
  936. WasmFunctionInfo* funsig = m_module->GetWasmFunctionInfo(i);
  937. const char16* name = ReadInlineName(len, fnNameLen);
  938. funsig->SetName(name, fnNameLen);
  939. uint32 numLocals = LEB128(len);
  940. if (numLocals != funsig->GetLocalCount())
  941. {
  942. ThrowDecodingError(_u("num locals mismatch in names section"));
  943. }
  944. for (uint32 j = 0; j < numLocals; ++j)
  945. {
  946. uint32 localNameLen = 0;
  947. ReadInlineName(len, localNameLen);
  948. }
  949. }
  950. }
  951. void WasmBinaryReader::ReadGlobalSection()
  952. {
  953. uint32 len = 0;
  954. uint32 numGlobals = LEB128(len);
  955. uint32 totalGlobals = 0;
  956. if (UInt32Math::Add(numGlobals, m_module->GetGlobalCount(), &totalGlobals) || totalGlobals > Limits::GetMaxGlobals())
  957. {
  958. ThrowDecodingError(_u("Too many globals"));
  959. }
  960. for (uint32 i = 0; i < numGlobals; ++i)
  961. {
  962. WasmTypes::WasmType type = ReadWasmType(len);
  963. if (!WasmTypes::IsLocalType(type))
  964. {
  965. ThrowDecodingError(_u("Invalid global type %u"), type);
  966. }
  967. switch (type)
  968. {
  969. case WasmTypes::I32: break; // Handled
  970. case WasmTypes::I64: break; // Handled
  971. case WasmTypes::F32: break; // Handled
  972. case WasmTypes::F64: break; // Handled
  973. #ifdef ENABLE_WASM_SIMD
  974. case WasmTypes::M128: ThrowDecodingError(_u("m128 globals not supported"));
  975. #endif
  976. default:
  977. WasmTypes::CompileAssertCases<WasmTypes::I32, WasmTypes::I64, WasmTypes::F32, WasmTypes::F64, WASM_M128_CHECK_TYPE>();
  978. }
  979. bool isMutable = ReadMutableValue();
  980. WasmNode globalNode = ReadInitExpr();
  981. GlobalReferenceTypes::Type refType = GlobalReferenceTypes::Const;
  982. WasmTypes::WasmType initType;
  983. switch (globalNode.op) {
  984. case wbI32Const: initType = WasmTypes::I32; break;
  985. case wbF32Const: initType = WasmTypes::F32; break;
  986. case wbF64Const: initType = WasmTypes::F64; break;
  987. case wbI64Const: initType = WasmTypes::I64; break;
  988. case wbGetGlobal:
  989. initType = m_module->GetGlobal(globalNode.var.num)->GetType();
  990. refType = GlobalReferenceTypes::LocalReference;
  991. break;
  992. default:
  993. Assert(UNREACHED);
  994. ThrowDecodingError(_u("Unknown global init_expr"));
  995. }
  996. if (type != initType)
  997. {
  998. ThrowDecodingError(_u("Type mismatch for global initialization"));
  999. }
  1000. m_module->AddGlobal(refType, type, isMutable, globalNode);
  1001. }
  1002. }
  1003. void WasmBinaryReader::ReadCustomSection()
  1004. {
  1005. CustomSection customSection;
  1006. customSection.name = m_currentSection.name;
  1007. customSection.nameLength = m_currentSection.nameLength;
  1008. customSection.payload = m_pc;
  1009. size_t size = m_currentSection.end - m_pc;
  1010. if (m_currentSection.end < m_pc || !Math::FitsInDWord(size))
  1011. {
  1012. ThrowDecodingError(_u("Invalid custom section size"));
  1013. }
  1014. customSection.payloadSize = (uint32)size;
  1015. m_module->AddCustomSection(customSection);
  1016. m_pc = m_currentSection.end;
  1017. }
  1018. const char16* WasmBinaryReader::ReadInlineName(uint32& length, uint32& nameLength)
  1019. {
  1020. uint32 rawNameLength = LEB128(length);
  1021. if (rawNameLength > Limits::GetMaxStringSize())
  1022. {
  1023. ThrowDecodingError(_u("Name too long"));
  1024. }
  1025. CheckBytesLeft(rawNameLength);
  1026. LPCUTF8 rawName = m_pc;
  1027. m_pc += rawNameLength;
  1028. length += rawNameLength;
  1029. utf8::DecodeOptions decodeOptions = utf8::doThrowOnInvalidWCHARs;
  1030. try
  1031. {
  1032. nameLength = (uint32)utf8::ByteIndexIntoCharacterIndex(rawName, rawNameLength, decodeOptions);
  1033. char16* contents = AnewArray(m_alloc, char16, nameLength + 1);
  1034. size_t decodedLength = utf8::DecodeUnitsIntoAndNullTerminate(contents, rawName, rawName + rawNameLength, decodeOptions);
  1035. if (decodedLength != nameLength)
  1036. {
  1037. AssertMsg(UNREACHED, "We calculated the length before decoding, what happened ?");
  1038. ThrowDecodingError(_u("Error while decoding utf8 string"));
  1039. }
  1040. return contents;
  1041. }
  1042. catch (utf8::InvalidWideCharException)
  1043. {
  1044. ThrowDecodingError(_u("Invalid UTF-8 encoding"));
  1045. }
  1046. }
  1047. void WasmBinaryReader::ReadImportSection()
  1048. {
  1049. uint32 len = 0;
  1050. uint32 numImports = LEB128(len);
  1051. if (numImports > Limits::GetMaxImports())
  1052. {
  1053. ThrowDecodingError(_u("Too many imports"));
  1054. }
  1055. for (uint32 i = 0; i < numImports; ++i)
  1056. {
  1057. uint32 modNameLen = 0, fnNameLen = 0;
  1058. const char16* modName = ReadInlineName(len, modNameLen);
  1059. const char16* fnName = ReadInlineName(len, fnNameLen);
  1060. ExternalKinds kind = ReadExternalKind();
  1061. TRACE_WASM_DECODER(_u("Import #%u: \"%s\".\"%s\", kind: %d"), i, modName, fnName, kind);
  1062. switch (kind)
  1063. {
  1064. case ExternalKinds::Function:
  1065. {
  1066. uint32 sigId = LEB128(len);
  1067. m_module->AddFunctionImport(sigId, modName, modNameLen, fnName, fnNameLen);
  1068. if (m_module->GetWasmFunctionCount() > Limits::GetMaxFunctions())
  1069. {
  1070. ThrowDecodingError(_u("Too many functions"));
  1071. }
  1072. break;
  1073. }
  1074. case ExternalKinds::Global:
  1075. {
  1076. WasmTypes::WasmType type = ReadWasmType(len);
  1077. bool isMutable = ReadMutableValue();
  1078. if (isMutable)
  1079. {
  1080. ThrowDecodingError(_u("Mutable globals cannot be imported"));
  1081. }
  1082. m_module->AddGlobal(GlobalReferenceTypes::ImportedReference, type, isMutable, {});
  1083. m_module->AddGlobalImport(modName, modNameLen, fnName, fnNameLen);
  1084. if (m_module->GetGlobalCount() > Limits::GetMaxGlobals())
  1085. {
  1086. ThrowDecodingError(_u("Too many globals"));
  1087. }
  1088. break;
  1089. }
  1090. case ExternalKinds::Table:
  1091. ReadTableSection(true);
  1092. m_module->AddTableImport(modName, modNameLen, fnName, fnNameLen);
  1093. break;
  1094. case ExternalKinds::Memory:
  1095. ReadMemorySection(true);
  1096. m_module->AddMemoryImport(modName, modNameLen, fnName, fnNameLen);
  1097. break;
  1098. default:
  1099. ThrowDecodingError(_u("Imported Kind %d, NYI"), kind);
  1100. break;
  1101. }
  1102. }
  1103. }
  1104. void WasmBinaryReader::ReadStartFunction()
  1105. {
  1106. uint32 len = 0;
  1107. uint32 id = LEB128(len);
  1108. Wasm::FunctionIndexTypes::Type funcType = m_module->GetFunctionIndexType(id);
  1109. if (!FunctionIndexTypes::CanBeExported(funcType))
  1110. {
  1111. ThrowDecodingError(_u("Invalid function index for start function %u"), id);
  1112. }
  1113. WasmSignature* sig = m_module->GetWasmFunctionInfo(id)->GetSignature();
  1114. if (sig->GetParamCount() > 0 || sig->GetResultCount())
  1115. {
  1116. ThrowDecodingError(_u("Start function must be void and nullary"));
  1117. }
  1118. m_module->SetStartFunction(id);
  1119. }
  1120. template<typename LEBType, uint32 bits>
  1121. LEBType WasmBinaryReader::LEB128(uint32 &length)
  1122. {
  1123. CompileAssert((sizeof(LEBType) * 8) >= bits);
  1124. constexpr bool sign = LEBType(-1) < LEBType(0);
  1125. LEBType result = 0;
  1126. uint32 shift = 0;
  1127. byte b = 0;
  1128. length = 0;
  1129. constexpr uint32 maxReads = (uint32) (((bits % 7) == 0) ? bits/7 : bits/7 + 1);
  1130. CompileAssert(maxReads > 0);
  1131. for (uint32 i = 0; i < maxReads; ++i)
  1132. {
  1133. CheckBytesLeft(1);
  1134. b = *m_pc++;
  1135. ++length;
  1136. result = result | ((LEBType)(b & 0x7f) << shift);
  1137. if (sign)
  1138. {
  1139. shift += 7;
  1140. if ((b & 0x80) == 0)
  1141. break;
  1142. }
  1143. else
  1144. {
  1145. if ((b & 0x80) == 0)
  1146. break;
  1147. shift += 7;
  1148. }
  1149. }
  1150. if (b & 0x80 || m_pc > m_end)
  1151. {
  1152. ThrowDecodingError(_u("Invalid LEB128 format"));
  1153. }
  1154. if (sign && (shift < (sizeof(LEBType) * 8)) && (0x40 & b))
  1155. {
  1156. #pragma prefast(suppress:26453)
  1157. result |= ((~(LEBType)0) << shift);
  1158. }
  1159. return result;
  1160. }
  1161. WasmNode WasmBinaryReader::ReadInitExpr(bool isOffset)
  1162. {
  1163. if (m_readerState != READER_STATE_MODULE)
  1164. {
  1165. ThrowDecodingError(_u("Wasm reader in an invalid state to read init_expr"));
  1166. }
  1167. m_funcState.count = 0;
  1168. m_funcState.size = (uint32)(m_currentSection.end - m_pc);
  1169. #if TARGET_64
  1170. Assert(m_pc + m_funcState.size == m_currentSection.end);
  1171. #endif
  1172. ReadExpr();
  1173. WasmNode node = m_currentNode;
  1174. switch (node.op)
  1175. {
  1176. case wbI32Const:
  1177. case wbF32Const:
  1178. case wbI64Const:
  1179. case wbF64Const:
  1180. break;
  1181. case wbGetGlobal:
  1182. {
  1183. uint32 globalIndex = node.var.num;
  1184. WasmGlobal* global = m_module->GetGlobal(globalIndex);
  1185. if (global->GetReferenceType() != GlobalReferenceTypes::ImportedReference)
  1186. {
  1187. ThrowDecodingError(_u("initializer expression can only use imported globals"));
  1188. }
  1189. if (global->IsMutable())
  1190. {
  1191. ThrowDecodingError(_u("initializer expression cannot reference a mutable global"));
  1192. }
  1193. break;
  1194. }
  1195. default:
  1196. ThrowDecodingError(_u("Invalid initexpr opcode"));
  1197. }
  1198. if (ReadExpr() != wbEnd)
  1199. {
  1200. ThrowDecodingError(_u("Missing end opcode after init expr"));
  1201. }
  1202. if (isOffset)
  1203. {
  1204. m_module->ValidateInitExportForOffset(node);
  1205. }
  1206. return node;
  1207. }
  1208. template<typename SectionLimitType>
  1209. SectionLimitType WasmBinaryReader::ReadSectionLimitsBase(uint32 maxInitial, uint32 maxMaximum, const char16* errorMsg)
  1210. {
  1211. SectionLimitType limits;
  1212. uint32 length = 0;
  1213. limits.flags = (SectionLimits::Flags)LEB128(length);
  1214. limits.initial = LEB128(length);
  1215. limits.maximum = maxMaximum;
  1216. if (limits.HasMaximum())
  1217. {
  1218. limits.maximum = LEB128(length);
  1219. if (limits.maximum > maxMaximum)
  1220. {
  1221. ThrowDecodingError(_u("Maximum %s"), errorMsg);
  1222. }
  1223. }
  1224. if (limits.initial > maxInitial)
  1225. {
  1226. ThrowDecodingError(_u("Minimum %s"), errorMsg);
  1227. }
  1228. return limits;
  1229. }
  1230. // Do not use float version of ReadConst. Instead use integer version and reinterpret bits.
  1231. template<> double WasmBinaryReader::ReadConst<double>() { Assert(false); return 0; }
  1232. template<> float WasmBinaryReader::ReadConst<float>() { Assert(false); return 0; }
  1233. template <typename T>
  1234. T WasmBinaryReader::ReadConst()
  1235. {
  1236. CheckBytesLeft(sizeof(T));
  1237. T value = *((T*)m_pc);
  1238. m_pc += sizeof(T);
  1239. return value;
  1240. }
  1241. bool WasmBinaryReader::ReadMutableValue()
  1242. {
  1243. uint8 mutableValue = ReadConst<UINT8>();
  1244. switch (mutableValue)
  1245. {
  1246. case 0: return false;
  1247. case 1: return true;
  1248. default:
  1249. ThrowDecodingError(_u("invalid mutability"));
  1250. }
  1251. }
  1252. WasmTypes::WasmType WasmBinaryReader::ReadWasmType(uint32& length)
  1253. {
  1254. return LanguageTypes::ToWasmType(SLEB128<int8, 7>(length));
  1255. }
  1256. void WasmBinaryReader::CheckBytesLeft(uint32 bytesNeeded)
  1257. {
  1258. uint32 bytesLeft = (uint32)(m_end - m_pc);
  1259. if (bytesNeeded > bytesLeft)
  1260. {
  1261. ThrowDecodingError(_u("Out of file: Needed: %d, Left: %d"), bytesNeeded, bytesLeft);
  1262. }
  1263. }
  1264. } // namespace Wasm
  1265. #endif // ENABLE_WASM