WasmBinaryReader.cpp 36 KB

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