mirror of
https://github.com/XRPLF/rippled.git
synced 2026-03-02 18:52:33 +00:00
1593 lines
78 KiB
C++
1593 lines
78 KiB
C++
#ifdef _DEBUG
|
|
// #define DEBUG_OUTPUT 1
|
|
#endif
|
|
|
|
#include <test/app/TestHostFunctions.h>
|
|
|
|
#include <xrpl/tx/transactors/smart_escrow/HostFuncWrapper.h>
|
|
|
|
#include <source_location>
|
|
|
|
namespace xrpl {
|
|
namespace test {
|
|
|
|
bool
|
|
testGetDataIncrement();
|
|
|
|
using Add_proto = int32_t(int32_t, int32_t);
|
|
static wasm_trap_t*
|
|
Add(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
|
|
{
|
|
int32_t Val1 = params->data[0].of.i32;
|
|
int32_t Val2 = params->data[1].of.i32;
|
|
// printf("Host function \"Add\": %d + %d\n", Val1, Val2);
|
|
results->data[0] = WASM_I32_VAL(Val1 + Val2);
|
|
return nullptr;
|
|
}
|
|
|
|
std::vector<uint8_t> const
|
|
hexToBytes(std::string const& hex)
|
|
{
|
|
auto const ws = boost::algorithm::unhex(hex);
|
|
return Bytes(ws.begin(), ws.end());
|
|
}
|
|
|
|
std::optional<int32_t>
|
|
runFinishFunction(std::string const& code)
|
|
{
|
|
auto& engine = WasmEngine::instance();
|
|
auto const wasm = hexToBytes(code);
|
|
auto const re = engine.run(wasm, "finish");
|
|
if (re.has_value())
|
|
{
|
|
return std::optional<int32_t>(re->result);
|
|
}
|
|
else
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
}
|
|
|
|
struct Wasm_test : public beast::unit_test::suite
|
|
{
|
|
void
|
|
checkResult(
|
|
Expected<WasmResult<int32_t>, TER> re,
|
|
int32_t expectedResult,
|
|
int64_t expectedCost,
|
|
std::source_location const location = std::source_location::current())
|
|
{
|
|
auto const lineStr = " (" + std::to_string(location.line()) + ")";
|
|
if (BEAST_EXPECTS(re.has_value(), transToken(re.error()) + lineStr))
|
|
{
|
|
BEAST_EXPECTS(re->result == expectedResult, std::to_string(re->result) + lineStr);
|
|
BEAST_EXPECTS(re->cost == expectedCost, std::to_string(re->cost) + lineStr);
|
|
}
|
|
}
|
|
|
|
void
|
|
testGetDataHelperFunctions()
|
|
{
|
|
testcase("getData helper functions");
|
|
BEAST_EXPECT(testGetDataIncrement());
|
|
}
|
|
|
|
void
|
|
testWasmLib()
|
|
{
|
|
testcase("wasmtime lib test");
|
|
// clang-format off
|
|
/* The WASM module buffer. */
|
|
Bytes const wasm = {/* WASM header */
|
|
0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00,
|
|
/* Type section */
|
|
0x01, 0x07, 0x01,
|
|
/* function type {i32, i32} -> {i32} */
|
|
0x60, 0x02, 0x7F, 0x7F, 0x01, 0x7F,
|
|
/* Import section */
|
|
0x02, 0x13, 0x01,
|
|
/* module name: "extern" */
|
|
0x06, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6E,
|
|
/* extern name: "func-add" */
|
|
0x08, 0x66, 0x75, 0x6E, 0x63, 0x2D, 0x61, 0x64, 0x64,
|
|
/* import desc: func 0 */
|
|
0x00, 0x00,
|
|
/* Function section */
|
|
0x03, 0x02, 0x01, 0x00,
|
|
/* Export section */
|
|
0x07, 0x0A, 0x01,
|
|
/* export name: "addTwo" */
|
|
0x06, 0x61, 0x64, 0x64, 0x54, 0x77, 0x6F,
|
|
/* export desc: func 0 */
|
|
0x00, 0x01,
|
|
/* Code section */
|
|
0x0A, 0x0A, 0x01,
|
|
/* code body */
|
|
0x08, 0x00, 0x20, 0x00, 0x20, 0x01, 0x10, 0x00, 0x0B};
|
|
// clang-format on
|
|
auto& vm = WasmEngine::instance();
|
|
|
|
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
|
|
WasmImpFunc<Add_proto>(*imports, "func-add", reinterpret_cast<void*>(&Add));
|
|
|
|
auto re = vm.run(wasm, "addTwo", wasmParams(1234, 5678), imports);
|
|
|
|
// if (res) printf("invokeAdd get the result: %d\n", res.value());
|
|
|
|
checkResult(re, 6'912, 59);
|
|
}
|
|
|
|
void
|
|
testBadWasm()
|
|
{
|
|
testcase("bad wasm test");
|
|
|
|
using namespace test::jtx;
|
|
|
|
Env env{*this};
|
|
std::shared_ptr<HostFunctions> hfs(new HostFunctions(env.journal));
|
|
|
|
{
|
|
auto wasm = hexToBytes("00000000");
|
|
std::string funcName("mock_escrow");
|
|
|
|
auto re = runEscrowWasm(wasm, hfs, funcName, {}, 15);
|
|
BEAST_EXPECT(!re);
|
|
}
|
|
|
|
{
|
|
auto wasm = hexToBytes("00112233445566778899AA");
|
|
std::string funcName("mock_escrow");
|
|
|
|
auto const re = preflightEscrowWasm(wasm, hfs, funcName);
|
|
BEAST_EXPECT(!isTesSuccess(re));
|
|
}
|
|
|
|
{
|
|
// FinishFunction wrong function name
|
|
// pub fn bad() -> bool {
|
|
// unsafe { host_lib::getLedgerSqn() >= 5 }
|
|
// }
|
|
auto const badWasm = hexToBytes(
|
|
"0061736d010000000105016000017f02190108686f73745f6c69620c6765"
|
|
"744c656467657253716e00000302010005030100100611027f00418080c0"
|
|
"000b7f00418080c0000b072b04066d656d6f727902000362616400010a5f"
|
|
"5f646174615f656e6403000b5f5f686561705f6261736503010a09010700"
|
|
"100041044a0b004d0970726f64756365727302086c616e67756167650104"
|
|
"52757374000c70726f6365737365642d6279010572757374631d312e3835"
|
|
"2e31202834656231363132353020323032352d30332d31352900490f7461"
|
|
"726765745f6665617475726573042b0f6d757461626c652d676c6f62616c"
|
|
"732b087369676e2d6578742b0f7265666572656e63652d74797065732b0a"
|
|
"6d756c746976616c7565");
|
|
|
|
auto const re = preflightEscrowWasm(badWasm, hfs, ESCROW_FUNCTION_NAME);
|
|
BEAST_EXPECT(!isTesSuccess(re));
|
|
}
|
|
}
|
|
|
|
void
|
|
testWasmLedgerSqn()
|
|
{
|
|
testcase("Wasm get ledger sequence");
|
|
|
|
auto ledgerSqnWasm = hexToBytes(ledgerSqnWasmHex);
|
|
|
|
using namespace test::jtx;
|
|
|
|
Env env{*this};
|
|
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
|
|
auto imports = std::make_shared<ImportVec>();
|
|
WASM_IMPORT_FUNC2(*imports, getLedgerSqn, "get_ledger_sqn", hfs.get(), 33);
|
|
auto& engine = WasmEngine::instance();
|
|
|
|
auto re = engine.run(ledgerSqnWasm, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
|
|
|
|
checkResult(re, 0, 440);
|
|
|
|
env.close();
|
|
env.close();
|
|
|
|
// empty module - run the same instance
|
|
re = engine.run({}, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
|
|
|
|
checkResult(re, 5, 488);
|
|
}
|
|
|
|
void
|
|
testWasmFib()
|
|
{
|
|
testcase("Wasm fibo");
|
|
|
|
auto const fibWasm = hexToBytes(fibWasmHex);
|
|
auto& engine = WasmEngine::instance();
|
|
|
|
auto const re = engine.run(fibWasm, "fib", wasmParams(10));
|
|
|
|
checkResult(re, 55, 1'137);
|
|
}
|
|
|
|
void
|
|
testWasmSha()
|
|
{
|
|
testcase("Wasm sha");
|
|
|
|
auto const sha512Wasm = hexToBytes(sha512PureWasmHex);
|
|
auto& engine = WasmEngine::instance();
|
|
|
|
auto const re = engine.run(sha512Wasm, "sha512_process", wasmParams(sha512PureWasmHex));
|
|
|
|
checkResult(re, 34'432, 151'155);
|
|
}
|
|
|
|
void
|
|
testWasmB58()
|
|
{
|
|
testcase("Wasm base58");
|
|
auto const b58Wasm = hexToBytes(b58WasmHex);
|
|
auto& engine = WasmEngine::instance();
|
|
|
|
Bytes outb;
|
|
outb.resize(1024);
|
|
|
|
auto const minSize = std::min(static_cast<std::uint32_t>(512), static_cast<std::uint32_t>(b58WasmHex.size()));
|
|
auto const s = std::string_view(b58WasmHex.c_str(), minSize);
|
|
|
|
auto const re = engine.run(b58Wasm, "b58enco", wasmParams(outb, s));
|
|
|
|
checkResult(re, 700, 2'886'069);
|
|
}
|
|
|
|
void
|
|
testHFCost()
|
|
{
|
|
testcase("wasm test host functions cost");
|
|
|
|
using namespace test::jtx;
|
|
|
|
Env env(*this);
|
|
{
|
|
auto const allHostFuncWasm = hexToBytes(allHostFunctionsWasmHex);
|
|
|
|
auto& engine = WasmEngine::instance();
|
|
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
auto imp = createWasmImport(*hfs);
|
|
for (auto& i : *imp)
|
|
i.second.gas = 0;
|
|
|
|
auto re = engine.run(allHostFuncWasm, ESCROW_FUNCTION_NAME, {}, imp, hfs, 1'000'000, env.journal);
|
|
|
|
checkResult(re, 1, 27'080);
|
|
|
|
env.close();
|
|
}
|
|
|
|
env.close();
|
|
env.close();
|
|
env.close();
|
|
env.close();
|
|
env.close();
|
|
|
|
{
|
|
auto const allHostFuncWasm = hexToBytes(allHostFunctionsWasmHex);
|
|
|
|
auto& engine = WasmEngine::instance();
|
|
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
auto const imp = createWasmImport(*hfs);
|
|
|
|
auto re = engine.run(allHostFuncWasm, ESCROW_FUNCTION_NAME, {}, imp, hfs, 1'000'000, env.journal);
|
|
|
|
checkResult(re, 1, 66'340);
|
|
|
|
env.close();
|
|
}
|
|
|
|
// not enough gas
|
|
{
|
|
auto const allHostFuncWasm = hexToBytes(allHostFunctionsWasmHex);
|
|
|
|
auto& engine = WasmEngine::instance();
|
|
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
auto const imp = createWasmImport(*hfs);
|
|
|
|
auto re = engine.run(allHostFuncWasm, ESCROW_FUNCTION_NAME, {}, imp, hfs, 200, env.journal);
|
|
|
|
if (BEAST_EXPECT(!re))
|
|
{
|
|
BEAST_EXPECTS(re.error() == tecFAILED_PROCESSING, std::to_string(TERtoInt(re.error())));
|
|
}
|
|
|
|
env.close();
|
|
}
|
|
}
|
|
|
|
void
|
|
testEscrowWasmDN()
|
|
{
|
|
testcase("escrow wasm devnet test");
|
|
|
|
auto const allHFWasm = hexToBytes(allHostFunctionsWasmHex);
|
|
|
|
using namespace test::jtx;
|
|
Env env{*this};
|
|
{
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
auto re = runEscrowWasm(allHFWasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
|
|
checkResult(re, 1, 66'340);
|
|
}
|
|
|
|
{
|
|
// max<int64_t>() gas
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
auto re = runEscrowWasm(allHFWasm, hfs, ESCROW_FUNCTION_NAME, {}, -1);
|
|
checkResult(re, 1, 66'340);
|
|
}
|
|
|
|
{ // fail because trying to access nonexistent field
|
|
struct FieldNotFoundHostFunctions : public TestHostFunctions
|
|
{
|
|
explicit FieldNotFoundHostFunctions(Env& env) : TestHostFunctions(env)
|
|
{
|
|
}
|
|
Expected<Bytes, HostFunctionError>
|
|
getTxField(SField const& fname) override
|
|
{
|
|
return Unexpected(HostFunctionError::FIELD_NOT_FOUND);
|
|
}
|
|
};
|
|
|
|
std::shared_ptr<HostFunctions> hfs(new FieldNotFoundHostFunctions(env));
|
|
auto re = runEscrowWasm(allHFWasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
|
|
checkResult(re, -201, 28'965);
|
|
}
|
|
|
|
{ // fail because trying to allocate more than MAX_PAGES memory
|
|
struct OversizedFieldHostFunctions : public TestHostFunctions
|
|
{
|
|
explicit OversizedFieldHostFunctions(Env& env) : TestHostFunctions(env)
|
|
{
|
|
}
|
|
Expected<Bytes, HostFunctionError>
|
|
getTxField(SField const& fname) override
|
|
{
|
|
return Bytes((128 + 1) * 64 * 1024, 1);
|
|
}
|
|
};
|
|
|
|
std::shared_ptr<HostFunctions> hfs(new OversizedFieldHostFunctions(env));
|
|
auto re = runEscrowWasm(allHFWasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
|
|
checkResult(re, -201, 28'965);
|
|
}
|
|
|
|
{ // fail because recursion too deep
|
|
|
|
auto const deepWasm = hexToBytes(deepRecursionHex);
|
|
|
|
std::shared_ptr<TestHostFunctionsSink> hfs(new TestHostFunctionsSink(env));
|
|
std::string funcName("finish");
|
|
auto re = runEscrowWasm(deepWasm, hfs, funcName, {}, 1'000'000'000);
|
|
BEAST_EXPECT(!re && re.error());
|
|
// std::cout << "bad case (deep recursion) result " << re.error()
|
|
// << std::endl;
|
|
|
|
auto const& sink = hfs->getSink();
|
|
auto countSubstr = [](std::string const& str, std::string const& substr) {
|
|
std::size_t pos = 0;
|
|
int occurrences = 0;
|
|
while ((pos = str.find(substr, pos)) != std::string::npos)
|
|
{
|
|
occurrences++;
|
|
pos += substr.length();
|
|
}
|
|
return occurrences;
|
|
};
|
|
|
|
auto const s = sink.messages().str();
|
|
BEAST_EXPECT(countSubstr(s, "WASMI Error: failure to call func") == 1);
|
|
BEAST_EXPECT(countSubstr(s, "exception: <finish> failure") > 0);
|
|
}
|
|
|
|
{ // infinite loop
|
|
auto const infiniteLoopWasm = hexToBytes(infiniteLoopWasmHex);
|
|
std::string const funcName("loop");
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
|
|
// infinite loop should be caught and fail
|
|
auto const re = runEscrowWasm(infiniteLoopWasm, hfs, funcName, {}, 1'000'000);
|
|
if (BEAST_EXPECT(!re.has_value()))
|
|
{
|
|
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
|
}
|
|
}
|
|
|
|
{
|
|
// expected import not provided
|
|
auto const lgrSqnWasm = hexToBytes(ledgerSqnWasmHex);
|
|
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
|
|
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
|
|
WASM_IMPORT_FUNC2(*imports, getLedgerSqn, "get_ledger_sqn2", hfs.get());
|
|
|
|
auto& engine = WasmEngine::instance();
|
|
|
|
auto re = engine.run(lgrSqnWasm, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
|
|
|
|
BEAST_EXPECT(!re);
|
|
}
|
|
|
|
{
|
|
// bad import format
|
|
auto const lgrSqnWasm = hexToBytes(ledgerSqnWasmHex);
|
|
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
|
|
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
|
|
WASM_IMPORT_FUNC2(*imports, getLedgerSqn, "get_ledger_sqn", hfs.get());
|
|
(*imports)[0].first = nullptr;
|
|
|
|
auto& engine = WasmEngine::instance();
|
|
|
|
auto re = engine.run(lgrSqnWasm, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
|
|
|
|
BEAST_EXPECT(!re);
|
|
}
|
|
|
|
{
|
|
// bad function name
|
|
auto const lgrSqnWasm = hexToBytes(ledgerSqnWasmHex);
|
|
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
|
|
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
|
|
WASM_IMPORT_FUNC2(*imports, getLedgerSqn, "get_ledger_sqn", hfs.get());
|
|
|
|
auto& engine = WasmEngine::instance();
|
|
auto re = engine.run(lgrSqnWasm, "func1", {}, imports, hfs, 1'000'000, env.journal);
|
|
|
|
BEAST_EXPECT(!re);
|
|
}
|
|
}
|
|
|
|
void
|
|
testFloat()
|
|
{
|
|
testcase("float point");
|
|
|
|
std::string const funcName("finish");
|
|
|
|
using namespace test::jtx;
|
|
|
|
Env env(*this);
|
|
{
|
|
auto const floatTestWasm = hexToBytes(floatTestsWasmHex);
|
|
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
auto re = runEscrowWasm(floatTestWasm, hfs, funcName, {}, 200'000);
|
|
checkResult(re, 1, 110'699);
|
|
env.close();
|
|
}
|
|
|
|
{
|
|
auto const float0Wasm = hexToBytes(float0Hex);
|
|
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
auto re = runEscrowWasm(float0Wasm, hfs, funcName, {}, 100'000);
|
|
checkResult(re, 1, 4'259);
|
|
env.close();
|
|
}
|
|
}
|
|
|
|
void
|
|
perfTest()
|
|
{
|
|
testcase("Perf test host functions");
|
|
|
|
using namespace jtx;
|
|
using namespace std::chrono;
|
|
|
|
// std::string const funcName("test");
|
|
auto const perfWasm = hexToBytes(hfPerfTest);
|
|
|
|
// std::string const credType = "abcde";
|
|
// std::string const credType2 = "fghijk";
|
|
// std::string const credType3 = "0123456";
|
|
// char const uri[] = "uri";
|
|
|
|
Account const alan{"alan"};
|
|
Account const bob{"bob"};
|
|
Account const issuer{"issuer"};
|
|
|
|
{
|
|
Env env(*this);
|
|
// Env env(*this, envconfig(), {}, nullptr,
|
|
// beast::severities::kTrace);
|
|
env.fund(XRP(5000), alan, bob, issuer);
|
|
env.close();
|
|
|
|
// // create escrow
|
|
// auto const seq = env.seq(alan);
|
|
// auto const k = keylet::escrow(alan, seq);
|
|
// // auto const allowance = 3'600;
|
|
// auto escrowCreate = escrow::create(alan, bob, XRP(1000));
|
|
// XRPAmount txnFees = env.current()->fees().base + 1000;
|
|
// env(escrowCreate,
|
|
// escrow::finish_function(wasmHex),
|
|
// escrow::finish_time(env.now() + 11s),
|
|
// escrow::cancel_time(env.now() + 100s),
|
|
// escrow::data("1000000000"), // 1000 XRP in drops
|
|
// memodata("memo1234567"),
|
|
// memodata("2memo1234567"),
|
|
// fee(txnFees));
|
|
|
|
// // create depositPreauth
|
|
// auto const k = keylet::depositPreauth(
|
|
// bob,
|
|
// {{issuer.id(), makeSlice(credType)},
|
|
// {issuer.id(), makeSlice(credType2)},
|
|
// {issuer.id(), makeSlice(credType3)}});
|
|
// env(deposit::authCredentials(
|
|
// bob,
|
|
// {{issuer, credType},
|
|
// {issuer, credType2},
|
|
// {issuer, credType3}}));
|
|
|
|
// create nft
|
|
[[maybe_unused]] uint256 const nft0{token::getNextID(env, alan, 0u)};
|
|
env(token::mint(alan, 0u));
|
|
auto const k = keylet::nftoffer(alan, 0);
|
|
[[maybe_unused]] uint256 const nft1{token::getNextID(env, alan, 0u)};
|
|
|
|
env(token::mint(alan, 0u),
|
|
token::uri(
|
|
"https://github.com/XRPLF/XRPL-Standards/discussions/"
|
|
"279?id=github.com/XRPLF/XRPL-Standards/discussions/"
|
|
"279&ut=github.com/XRPLF/XRPL-Standards/discussions/"
|
|
"279&sid=github.com/XRPLF/XRPL-Standards/discussions/"
|
|
"279&aot=github.com/XRPLF/XRPL-Standards/disc"));
|
|
[[maybe_unused]] uint256 const nft2{token::getNextID(env, alan, 0u)};
|
|
env(token::mint(alan, 0u));
|
|
env.close();
|
|
|
|
std::shared_ptr<HostFunctions> hfs(new PerfHostFunctions(env, k, env.tx()));
|
|
|
|
auto re = runEscrowWasm(perfWasm, hfs, ESCROW_FUNCTION_NAME);
|
|
if (BEAST_EXPECT(re.has_value()))
|
|
{
|
|
BEAST_EXPECT(re->result);
|
|
std::cout << "Res: " << re->result << " cost: " << re->cost << std::endl;
|
|
}
|
|
|
|
// env(escrow::finish(alan, alan, seq),
|
|
// escrow::comp_allowance(allowance),
|
|
// fee(txnFees),
|
|
// ter(tesSUCCESS));
|
|
|
|
env.close();
|
|
}
|
|
}
|
|
|
|
void
|
|
testCodecovWasm()
|
|
{
|
|
testcase("Codecov wasm test");
|
|
|
|
using namespace test::jtx;
|
|
|
|
Env env{*this};
|
|
|
|
auto const codecovWasm = hexToBytes(codecovTestsWasmHex);
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
|
|
auto const allowance = 202'724;
|
|
auto re = runEscrowWasm(codecovWasm, hfs, ESCROW_FUNCTION_NAME, {}, allowance);
|
|
|
|
checkResult(re, 1, allowance);
|
|
}
|
|
|
|
void
|
|
testDisabledFloat()
|
|
{
|
|
testcase("disabled float");
|
|
|
|
using namespace test::jtx;
|
|
Env env{*this};
|
|
|
|
auto disabledFloatWasm = hexToBytes(disabledFloatHex);
|
|
std::string const funcName("finish");
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
|
|
{
|
|
// f32 set constant, opcode disabled exception
|
|
auto const re = runEscrowWasm(disabledFloatWasm, hfs, funcName, {}, 1'000'000);
|
|
if (BEAST_EXPECT(!re.has_value()))
|
|
{
|
|
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
|
}
|
|
}
|
|
|
|
{
|
|
// f32 add, can't create module exception
|
|
disabledFloatWasm[0x117] = 0x92;
|
|
auto const re = runEscrowWasm(disabledFloatWasm, hfs, funcName, {}, 1'000'000);
|
|
if (BEAST_EXPECT(!re.has_value()))
|
|
{
|
|
BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
testWasmMemory()
|
|
{
|
|
testcase("Wasm additional memory limit tests");
|
|
BEAST_EXPECT(runFinishFunction(memoryPointerAtLimitHex).value() == 1);
|
|
BEAST_EXPECT(runFinishFunction(memoryPointerOverLimitHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(memoryOffsetOverLimitHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(memoryEndOfWordOverLimitHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(memoryGrow0To1PageHex).value() == 1);
|
|
BEAST_EXPECT(runFinishFunction(memoryGrow1To0PageHex).value() == -1);
|
|
BEAST_EXPECT(runFinishFunction(memoryLastByteOf8MBHex).value() == 1);
|
|
BEAST_EXPECT(runFinishFunction(memoryGrow1MoreThan8MBHex).value() == -1);
|
|
BEAST_EXPECT(runFinishFunction(memoryGrow0MoreThan8MBHex).value() == 1);
|
|
BEAST_EXPECT(runFinishFunction(memoryInit1MoreThan8MBHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(memoryNegativeAddressHex).has_value() == false);
|
|
}
|
|
|
|
void
|
|
testWasmTable()
|
|
{
|
|
testcase("Wasm table limit tests");
|
|
BEAST_EXPECT(runFinishFunction(table64ElementsHex).value() == 1);
|
|
BEAST_EXPECT(runFinishFunction(table65ElementsHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(table2TablesHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(table0ElementsHex).value() == 1);
|
|
BEAST_EXPECT(runFinishFunction(tableUintMaxHex).has_value() == false);
|
|
}
|
|
|
|
void
|
|
testWasmProposal()
|
|
{
|
|
testcase("Wasm disabled proposal tests");
|
|
BEAST_EXPECT(runFinishFunction(proposalMutableGlobalHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(proposalGcStructNewHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(proposalMultiValueHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(proposalSignExtHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(proposalFloatToIntHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(proposalBulkMemoryHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(proposalRefTypesHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(proposalTailCallHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(proposalExtendedConstHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(proposalMultiMemoryHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(proposalCustomPageSizesHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(proposalMemory64Hex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(proposalWideArithmeticHex).has_value() == false);
|
|
}
|
|
|
|
void
|
|
testWasmTrap()
|
|
{
|
|
testcase("Wasm trap tests");
|
|
BEAST_EXPECT(runFinishFunction(trapDivideBy0Hex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(trapIntOverflowHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(trapUnreachableHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(trapNullCallHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(trapFuncSigMismatchHex).has_value() == false);
|
|
}
|
|
|
|
void
|
|
testWasmWasi()
|
|
{
|
|
testcase("Wasm Wasi tests");
|
|
BEAST_EXPECT(runFinishFunction(wasiGetTimeHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(wasiPrintHex).has_value() == false);
|
|
}
|
|
|
|
void
|
|
testWasmSectionCorruption()
|
|
{
|
|
testcase("Wasm Section Corruption tests");
|
|
BEAST_EXPECT(runFinishFunction(badMagicNumberHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(badVersionNumberHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(lyingHeaderHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(neverEndingNumberHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(vectorLieHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(sectionOrderingHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(ghostPayloadHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(junkAfterSectionHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(invalidSectionIdHex).has_value() == false);
|
|
BEAST_EXPECT(runFinishFunction(localVariableBombHex).has_value() == false);
|
|
}
|
|
|
|
void
|
|
testStartFunctionLoop()
|
|
{
|
|
testcase("infinite loop in start function");
|
|
|
|
using namespace test::jtx;
|
|
Env env(*this);
|
|
|
|
auto const startLoopWasm = hexToBytes(startLoopHex);
|
|
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
|
|
std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
|
|
|
|
auto& engine = WasmEngine::instance();
|
|
auto checkRes = engine.check(startLoopWasm, "finish", {}, imports, hfs, env.journal);
|
|
BEAST_EXPECTS(checkRes == tesSUCCESS, std::to_string(TERtoInt(checkRes)));
|
|
|
|
auto re = engine.run(startLoopWasm, ESCROW_FUNCTION_NAME, {}, imports, hfs, 1'000'000, env.journal);
|
|
BEAST_EXPECTS(re.error() == tecFAILED_PROCESSING, std::to_string(TERtoInt(re.error())));
|
|
}
|
|
|
|
void
|
|
testBadAlloc()
|
|
{
|
|
testcase("Wasm Bad Alloc");
|
|
|
|
// bad_alloc.c
|
|
auto const badAllocWasm = hexToBytes(badAllocHex);
|
|
|
|
using namespace test::jtx;
|
|
|
|
Env env{*this};
|
|
std::shared_ptr<HostFunctions> hfs(new TestLedgerDataProvider(env));
|
|
|
|
// std::shared_ptr<ImportVec> imports(std::make_shared<ImportVec>());
|
|
uint8_t buf1[8] = {7, 8, 9, 10, 11, 12, 13, 14};
|
|
{ // forged "allocate" return valid address
|
|
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = sizeof(buf1)}}}};
|
|
auto& engine = WasmEngine::instance();
|
|
|
|
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
|
|
if (BEAST_EXPECT(re))
|
|
{
|
|
BEAST_EXPECTS(re->result == 7, std::to_string(re->result));
|
|
BEAST_EXPECTS(re->cost == 430, std::to_string(re->cost));
|
|
}
|
|
}
|
|
|
|
{ // return 0 whithout calling wasm
|
|
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 0}}}};
|
|
auto& engine = WasmEngine::instance();
|
|
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
|
|
BEAST_EXPECT(!re) && BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
|
}
|
|
|
|
{ // forged "allocate" return 8Mb (which is more than memory limit)
|
|
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 1}}}};
|
|
auto& engine = WasmEngine::instance();
|
|
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
|
|
BEAST_EXPECT(!re) && BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
|
}
|
|
|
|
{ // forged "allocate" return 0
|
|
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 2}}}};
|
|
auto& engine = WasmEngine::instance();
|
|
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
|
|
BEAST_EXPECT(!re) && BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
|
}
|
|
|
|
{ // forged "allocate" return -1
|
|
std::vector<WasmParam> params = {{.type = WT_U8V, .of = {.u8v = {.d = buf1, .sz = 3}}}};
|
|
auto& engine = WasmEngine::instance();
|
|
auto re = engine.run(badAllocWasm, "test", params, {}, hfs, 1'000'000, env.journal);
|
|
|
|
BEAST_EXPECT(!re) && BEAST_EXPECT(re.error() == tecFAILED_PROCESSING);
|
|
}
|
|
|
|
{
|
|
std::string what;
|
|
try
|
|
{
|
|
char const test[] = "test";
|
|
std::size_t sz = std::numeric_limits<int32_t>::max() + 1ull;
|
|
auto p = wasmParams(std::string_view(test, sz));
|
|
}
|
|
catch (std::exception const& e)
|
|
{
|
|
what = e.what();
|
|
}
|
|
BEAST_EXPECT(what.find("can't allocate memory, size: 2147483648") != std::string::npos);
|
|
}
|
|
|
|
env.close();
|
|
}
|
|
|
|
void
|
|
testBadAlign()
|
|
{
|
|
testcase("Wasm Bad Align");
|
|
|
|
// bad_align.c
|
|
auto const badAlignWasm = hexToBytes(badAlignWasmHex);
|
|
|
|
using namespace test::jtx;
|
|
|
|
Env env{*this};
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
auto imports = createWasmImport(*hfs);
|
|
|
|
{ // Calls float_from_uint with bad alignment.
|
|
// Can be checked through codecov
|
|
auto& engine = WasmEngine::instance();
|
|
|
|
auto re = engine.run(badAlignWasm, "test", {}, imports, hfs, 1'000'000, env.journal);
|
|
if (BEAST_EXPECTS(re, transToken(re.error())))
|
|
{
|
|
BEAST_EXPECTS(re->result == 0x684f7941, std::to_string(re->result));
|
|
}
|
|
}
|
|
|
|
env.close();
|
|
}
|
|
|
|
void
|
|
testReturnType()
|
|
{
|
|
using namespace test::jtx;
|
|
Env env(*this);
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
|
|
testcase("Wasm invalid return type");
|
|
|
|
// return int64.
|
|
{ // (module
|
|
// (memory (export "memory") 1)
|
|
// (func (export "finish") (result i64)
|
|
// i64.const 0x100000000))
|
|
auto const wasmHex =
|
|
"0061736d010000000105016000017e030201000503010001"
|
|
"071302066d656d6f727902000666696e69736800000a0a01"
|
|
"08004280808080100b";
|
|
auto const wasm = hexToBytes(wasmHex);
|
|
auto const re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
|
|
BEAST_EXPECT(!re);
|
|
}
|
|
|
|
// return void. wasmi return execution error
|
|
{ //(module
|
|
// (type (;0;) (func))
|
|
// (func (;0;) (type 0)
|
|
// return)
|
|
// (memory (;0;) 1)
|
|
// (export "memory" (memory 0))
|
|
// (export "finish" (func 0)))
|
|
auto const wasmHex =
|
|
"0061736d01000000010401600000030201000503010001071302066d656d6f"
|
|
"727902000666696e69736800000a050103000f0b";
|
|
auto const wasm = hexToBytes(wasmHex);
|
|
auto const re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
|
|
BEAST_EXPECT(!re);
|
|
}
|
|
|
|
// return i32, i32. wasmi doesn't create module
|
|
{ //(module
|
|
// (memory (export "memory") 1)
|
|
// (func (export "finish") (result i32 i32)
|
|
// i32.const 0x10000000
|
|
// i32.const 0x100000FF))
|
|
auto const wasmHex =
|
|
"0061736d010000000106016000027f7f030201000503010001071302066d65"
|
|
"6d6f727902000666696e69736800000a10010e0041808080800141ff818080"
|
|
"010b";
|
|
auto const wasm = hexToBytes(wasmHex);
|
|
auto const re = runEscrowWasm(wasm, hfs, ESCROW_FUNCTION_NAME, {}, 100'000);
|
|
BEAST_EXPECT(!re);
|
|
}
|
|
}
|
|
|
|
void
|
|
testParameterType()
|
|
{
|
|
using namespace test::jtx;
|
|
Env env(*this);
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
|
|
testcase("Wasm invalid params");
|
|
|
|
// (module
|
|
// (memory (export "memory") 1)
|
|
// (func $test1 (export "test1") (param i32) (result i32)
|
|
// i32.const 1000)
|
|
// (func $test2 (export "test2") (param i32 i32) (result i32)
|
|
// i32.const 1001))
|
|
auto const wasmHex =
|
|
"0061736d01000000010c0260017f017f60027f7f017f03030200010503010001071a03066d656d6f7279020005746573743100"
|
|
"0005746573743200010a0d02050041e8070b050041e9070b";
|
|
auto const wasm = hexToBytes(wasmHex);
|
|
|
|
// good params, module is working properly
|
|
{
|
|
auto const re = runEscrowWasm(wasm, hfs, "test2", wasmParams(2, 10), 100'000);
|
|
BEAST_EXPECT(re && re->result == 1001 && re->cost == 37);
|
|
}
|
|
|
|
// no params
|
|
{
|
|
auto const re = runEscrowWasm(wasm, hfs, "test1", {}, 100'000);
|
|
BEAST_EXPECT(!re);
|
|
}
|
|
|
|
// more params
|
|
{
|
|
auto const re = runEscrowWasm(wasm, hfs, "test1", wasmParams(0, 1), 100'000);
|
|
BEAST_EXPECT(!re);
|
|
}
|
|
|
|
// less params
|
|
{
|
|
auto const re = runEscrowWasm(wasm, hfs, "test2", wasmParams(1), 100'000);
|
|
BEAST_EXPECT(!re);
|
|
}
|
|
|
|
// invalid type
|
|
{
|
|
auto const re = runEscrowWasm(wasm, hfs, "test1", wasmParams(std::int64_t(15)), 100'000);
|
|
BEAST_EXPECT(!re);
|
|
}
|
|
}
|
|
|
|
void
|
|
testSwapBytes()
|
|
{
|
|
testcase("Wasm swap bytes");
|
|
|
|
uint64_t const SWAP_DATAU64 = 0x123456789abcdeffull;
|
|
uint64_t const REVERSE_SWAP_DATAU64 = 0xffdebc9a78563412ull;
|
|
int64_t const SWAP_DATAI64 = 0x123456789abcdeffll;
|
|
int64_t const REVERSE_SWAP_DATAI64 = 0xffdebc9a78563412ll;
|
|
|
|
uint32_t const SWAP_DATAU32 = 0x12789aff;
|
|
uint32_t const REVERSE_SWAP_DATAU32 = 0xff9a7812;
|
|
int32_t const SWAP_DATAI32 = 0x12789aff;
|
|
int32_t const REVERSE_SWAP_DATAI32 = 0xff9a7812;
|
|
|
|
uint16_t const SWAP_DATAU16 = 0x12ff;
|
|
uint16_t const REVERSE_SWAP_DATAU16 = 0xff12;
|
|
int16_t const SWAP_DATAI16 = 0x12ff;
|
|
int16_t const REVERSE_SWAP_DATAI16 = 0xff12;
|
|
|
|
uint64_t b1 = SWAP_DATAU64;
|
|
int64_t b2 = SWAP_DATAI64;
|
|
b1 = adjustWasmEndianessHlp(b1);
|
|
b2 = adjustWasmEndianessHlp(b2);
|
|
BEAST_EXPECT(b1 == REVERSE_SWAP_DATAU64);
|
|
BEAST_EXPECT(b2 == REVERSE_SWAP_DATAI64);
|
|
b1 = adjustWasmEndianessHlp(b1);
|
|
b2 = adjustWasmEndianessHlp(b2);
|
|
BEAST_EXPECT(b1 == SWAP_DATAU64);
|
|
BEAST_EXPECT(b2 == SWAP_DATAI64);
|
|
|
|
uint32_t b3 = SWAP_DATAU32;
|
|
int32_t b4 = SWAP_DATAI32;
|
|
b3 = adjustWasmEndianessHlp(b3);
|
|
b4 = adjustWasmEndianessHlp(b4);
|
|
BEAST_EXPECT(b3 == REVERSE_SWAP_DATAU32);
|
|
BEAST_EXPECT(b4 == REVERSE_SWAP_DATAI32);
|
|
b3 = adjustWasmEndianessHlp(b3);
|
|
b4 = adjustWasmEndianessHlp(b4);
|
|
BEAST_EXPECT(b3 == SWAP_DATAU32);
|
|
BEAST_EXPECT(b4 == SWAP_DATAI32);
|
|
|
|
uint16_t b5 = SWAP_DATAU16;
|
|
int16_t b6 = SWAP_DATAI16;
|
|
b5 = adjustWasmEndianessHlp(b5);
|
|
b6 = adjustWasmEndianessHlp(b6);
|
|
BEAST_EXPECT(b5 == REVERSE_SWAP_DATAU16);
|
|
BEAST_EXPECT(b6 == REVERSE_SWAP_DATAI16);
|
|
b5 = adjustWasmEndianessHlp(b5);
|
|
b6 = adjustWasmEndianessHlp(b6);
|
|
BEAST_EXPECT(b5 == SWAP_DATAU16);
|
|
BEAST_EXPECT(b6 == SWAP_DATAI16);
|
|
}
|
|
|
|
void
|
|
testManyParams()
|
|
{
|
|
testcase("Wasm Many params");
|
|
|
|
auto const params1k = hexToBytes(thousandParamsHex);
|
|
auto const params1k1 = hexToBytes(thousand1ParamsHex);
|
|
|
|
using namespace test::jtx;
|
|
|
|
Env env{*this};
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
auto imports = createWasmImport(*hfs);
|
|
|
|
// add 1k parameter (max that wasmi support)
|
|
std::vector<WasmParam> params;
|
|
for (int i = 0; i < 1000; ++i)
|
|
params.push_back({.type = WT_I32, .of = {.i32 = 2 * i}});
|
|
|
|
auto& engine = WasmEngine::instance();
|
|
{
|
|
auto re = engine.run(params1k, "test", params, imports, hfs, 1'000'000, env.journal);
|
|
BEAST_EXPECT(re && re->result == 999000);
|
|
}
|
|
|
|
// add 1 more parameter, module can't be created now
|
|
params.push_back({.type = WT_I32, .of = {.i32 = 2 * 1000}});
|
|
{
|
|
auto re = engine.run(params1k1, "test", params, imports, hfs, 1'000'000, env.journal);
|
|
BEAST_EXPECT(!re);
|
|
}
|
|
|
|
// function that create 10k local variables
|
|
auto const locals10k = hexToBytes(locals10kHex);
|
|
{
|
|
auto re = engine.run(locals10k, "test", wasmParams(0, 1), imports, hfs, 1'000'000, env.journal);
|
|
BEAST_EXPECT(re && re->result == 890'489'442);
|
|
}
|
|
|
|
// module has 5k functions
|
|
auto const functions5k = hexToBytes(functions5kHex);
|
|
{
|
|
auto re = engine.run(functions5k, "test0001", wasmParams(2, 3), imports, hfs, 1'000'000, env.journal);
|
|
BEAST_EXPECT(re && re->result == 5);
|
|
}
|
|
|
|
env.close();
|
|
}
|
|
|
|
template <class IT>
|
|
std::size_t
|
|
uleb128(IT& it, std::uint16_t val)
|
|
{
|
|
std::size_t count = 0;
|
|
do
|
|
{
|
|
std::uint8_t byte = val & 0x7f;
|
|
val >>= 7;
|
|
if (val)
|
|
byte |= 0x80;
|
|
*it++ = byte;
|
|
++count;
|
|
} while (val != 0);
|
|
return count;
|
|
}
|
|
|
|
void
|
|
testOpcodes()
|
|
{
|
|
using namespace test::jtx;
|
|
|
|
unsigned const RESERVED = 64;
|
|
std::uint8_t nop = 0x01;
|
|
std::array<std::uint8_t, 16> const codeMarker = {
|
|
nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop, nop};
|
|
auto const opcReserved = hexToBytes(opcReservedHex);
|
|
|
|
Env env{*this};
|
|
auto& engine = WasmEngine::instance();
|
|
|
|
std::shared_ptr<HostFunctions> hfs(new TestHostFunctions(env, 0));
|
|
auto imports = createWasmImport(*hfs);
|
|
env.close();
|
|
|
|
{
|
|
auto run = [&](std::vector<uint8_t> const& code,
|
|
bool good = false,
|
|
int64_t cost = -1,
|
|
std::source_location const location = std::source_location::current()) {
|
|
auto const lineStr = " (" + std::to_string(location.line()) + ")";
|
|
auto re = engine.run(code, "all_instructions", {}, imports, hfs, 1'000'000, env.journal);
|
|
if (BEAST_EXPECTS(re.has_value() == good, transToken(re.error()) + lineStr) && good)
|
|
BEAST_EXPECTS(re->cost == cost, std::to_string(re->cost) + lineStr);
|
|
};
|
|
|
|
// 1 byte instruction
|
|
auto test = [&](std::uint8_t start,
|
|
std::uint8_t finish,
|
|
bool good = false,
|
|
int64_t cost = -1,
|
|
std::source_location const location = std::source_location::current()) {
|
|
auto const lineStr = " (" + std::to_string(location.line()) + ")";
|
|
auto code = opcReserved;
|
|
auto codeRange = std::ranges::search(code, codeMarker);
|
|
if (!BEAST_EXPECTS(!codeRange.empty(), lineStr))
|
|
return;
|
|
|
|
auto it = codeRange.begin();
|
|
for (std::uint16_t i = start; i <= finish; ++i)
|
|
{
|
|
*it = i;
|
|
run(code, good, cost, location);
|
|
}
|
|
};
|
|
|
|
// 2 bytes instruction
|
|
auto test2 = [&](std::uint8_t major,
|
|
std::uint16_t start,
|
|
std::uint16_t finish,
|
|
bool good = false,
|
|
int64_t cost = -1,
|
|
std::source_location const location = std::source_location::current()) {
|
|
auto const lineStr = " (" + std::to_string(location.line()) + ")";
|
|
auto code = opcReserved;
|
|
auto codeRange = std::ranges::search(code, codeMarker);
|
|
if (!BEAST_EXPECTS(!codeRange.empty(), lineStr))
|
|
return;
|
|
|
|
auto it = codeRange.begin();
|
|
*it++ = major;
|
|
for (std::uint16_t i = start; i <= finish; ++i)
|
|
{
|
|
auto it2 = it;
|
|
uleb128(it2, i);
|
|
run(code, good, cost, location);
|
|
}
|
|
};
|
|
|
|
// multibytes instructions
|
|
auto testMB = [&](std::vector<std::uint8_t> const& codeSnap,
|
|
bool good = false,
|
|
int64_t cost = -1,
|
|
std::source_location const location = std::source_location::current()) {
|
|
auto const lineStr = " (" + std::to_string(location.line()) + ")";
|
|
auto code = opcReserved;
|
|
auto codeRange = std::ranges::search(code, codeMarker);
|
|
if (!BEAST_EXPECTS(!codeRange.empty(), lineStr))
|
|
return;
|
|
|
|
if (!BEAST_EXPECTS(codeSnap.size() < RESERVED, lineStr))
|
|
return;
|
|
auto it = codeRange.begin();
|
|
for (auto x : codeSnap)
|
|
*it++ = x;
|
|
run(code, good, cost, location);
|
|
};
|
|
|
|
// normal run
|
|
testcase("Wasm reserved opcodes main");
|
|
test(nop, nop, true, 534);
|
|
|
|
// reserved main
|
|
test(0x06, 0x0A);
|
|
test(0x12, 0x19);
|
|
test(0x25, 0x27);
|
|
test(0xC0, 0xFA);
|
|
test(0xFF, 0xFF);
|
|
|
|
// reserved gc, string
|
|
testcase("Wasm reserved opcodes gc");
|
|
test2(0xFB, 0x00, 0xBF); // not supported by compiler
|
|
|
|
// reserved FC
|
|
testcase("Wasm reserved opcodes FC");
|
|
test2(0xFC, 0x00, 0x07); // floats, disabled
|
|
test2(0xFC, 0x12, 0x1F);
|
|
|
|
// reserved SIMD
|
|
testcase("Wasm reserved opcodes SIMD");
|
|
test2(0xFD, 0x9A, 0x9A);
|
|
test2(0xFD, 0xA2, 0xA2);
|
|
test2(0xFD, 0xA5, 0xA6);
|
|
test2(0xFD, 0xAF, 0xB0);
|
|
test2(0xFD, 0xB2, 0xB4);
|
|
test2(0xFD, 0xB8, 0xB8);
|
|
test2(0xFD, 0xC2, 0xC2);
|
|
test2(0xFD, 0xC5, 0xC6);
|
|
test2(0xFD, 0xCF, 0xD0);
|
|
test2(0xFD, 0xD2, 0xD4);
|
|
test2(0xFD, 0xE2, 0xE2);
|
|
test2(0xFD, 0xEE, 0xEE);
|
|
test2(0xFD, 0x115, 0x12F);
|
|
|
|
testcase("Wasm opcodes THREADS");
|
|
test2(0xFE, 0x00, 0x4F); // not supported by compiler
|
|
|
|
// FC mem instructions
|
|
testMB({0x41, 0x00, 0x41, 0x00, 0x41, 0x04, 0xFC, 0x08, 0x00, 0x00}); // memory.init
|
|
testMB({0xFC, 0x09, 0x00}); // data.drop
|
|
testMB({0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0xFC, 0x0A, 0x00, 0x00}); // memory.copy
|
|
testMB({0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0xFC, 0x0B, 0x00}); // memory.fill
|
|
testMB({0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0xFC, 0x0C, 0x00, 0x00}); // table.init
|
|
testMB({0xFC, 0x0D, 0x00}); // elem.drop
|
|
testMB({0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0xFC, 0x0E, 0x00, 0x00}); // table.copy
|
|
testMB({0xD2, 0x00, 0x41, 0x00, 0xFC, 0x0F, 0x00, 0x1A}); // table.grow
|
|
testMB({0x1A, 0xFC, 0x10, 0x00, 0x1A}); // table.size
|
|
testMB({0x41, 0x00, 0xD2, 0x00, 0x41, 0x00, 0xFC, 0x11, 0x00}); // table.fill
|
|
|
|
testcase("Wasm opcodes SIMD");
|
|
// clang-format off
|
|
|
|
// generated by auggie
|
|
// SIMD instructions
|
|
testMB({0x41, 0x00, 0xFD, 0x00, 0x04, 0x00, 0x1A}); // v128.load
|
|
testMB({0x41, 0x00, 0xFD, 0x01, 0x03, 0x00, 0x1A}); // v128.load8x8_s
|
|
testMB({0x41, 0x00, 0xFD, 0x02, 0x03, 0x00, 0x1A}); // v128.load8x8_u
|
|
testMB({0x41, 0x00, 0xFD, 0x03, 0x03, 0x00, 0x1A}); // v128.load16x4_s
|
|
testMB({0x41, 0x00, 0xFD, 0x04, 0x03, 0x00, 0x1A}); // v128.load16x4_u
|
|
testMB({0x41, 0x00, 0xFD, 0x05, 0x03, 0x00, 0x1A}); // v128.load32x2_s
|
|
testMB({0x41, 0x00, 0xFD, 0x06, 0x03, 0x00, 0x1A}); // v128.load32x2_u
|
|
testMB({0x41, 0x00, 0xFD, 0x07, 0x00, 0x00, 0x1A}); // v128.load8_splat
|
|
testMB({0x41, 0x00, 0xFD, 0x08, 0x01, 0x00, 0x1A}); // v128.load16_splat
|
|
testMB({0x41, 0x00, 0xFD, 0x09, 0x02, 0x00, 0x1A}); // v128.load32_splat
|
|
testMB({0x41, 0x00, 0xFD, 0x0A, 0x03, 0x00, 0x1A}); // v128.load64_splat
|
|
testMB({0x41, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0B, 0x04, 0x00}); // v128.store
|
|
testMB({0xFD, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00,
|
|
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1A}); // v128.const
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0D, 0x00, 0x01, 0x02, 0x03,
|
|
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1A}); // i8x16.shuffle
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0E, 0x1A}); // i8x16.swizzle
|
|
testMB({0x41, 0x2A, 0xFD, 0x0F, 0x1A}); // i8x16.splat
|
|
testMB({0x41, 0x2A, 0xFD, 0x10, 0x1A}); // i16x8.splat
|
|
testMB({0x41, 0x2A, 0xFD, 0x11, 0x1A}); // i32x4.splat
|
|
testMB({0x42, 0x2A, 0xFD, 0x12, 0x1A}); // i64x2.splat
|
|
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x15, 0x00, 0x1A}); // i8x16.extract_lane_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x16, 0x00, 0x1A}); // i8x16.extract_lane_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2A, 0xFD, 0x17, 0x00, 0x1A}); // i8x16.replace_lane
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x18, 0x00, 0x1A}); // i16x8.extract_lane_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x19, 0x00, 0x1A}); // i16x8.extract_lane_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2A, 0xFD, 0x1A, 0x00, 0x1A}); // i16x8.replace_lane
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x1B, 0x00, 0x1A}); // i32x4.extract_lane
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x2A, 0xFD, 0x1C, 0x00, 0x1A}); // i32x4.replace_lane
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x1D, 0x00, 0x1A}); // i64x2.extract_lane
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x2A, 0xFD, 0x1E, 0x00, 0x1A}); // i64x2.replace_lane
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x1F, 0x00, 0x1A}); // f32x4.extract_lane
|
|
testMB(
|
|
{0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x80, 0x3F, 0xFD, 0x20, 0x00, 0x1A}); // f32x4.replace_lane
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x21, 0x00, 0x1A}); // f64x2.extract_lane
|
|
testMB(
|
|
{0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0xFD, 0x22, 0x00, 0x1A}); // f64x2.replace_lane
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x23, 0x1A}); // i8x16.eq
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x24, 0x1A}); // i8x16.ne
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x25, 0x1A}); // i8x16.lt_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x26, 0x1A}); // i8x16.lt_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x27, 0x1A}); // i8x16.gt_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x28, 0x1A}); // i8x16.gt_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x29, 0x1A}); // i8x16.le_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x2A, 0x1A}); // i8x16.le_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x2B, 0x1A}); // i8x16.ge_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x2C, 0x1A}); // i8x16.ge_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x2D, 0x1A}); // i16x8.eq
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x2E, 0x1A}); // i16x8.ne
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x2F, 0x1A}); // i16x8.lt_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x30, 0x1A}); // i16x8.lt_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x31, 0x1A}); // i16x8.gt_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x32, 0x1A}); // i16x8.gt_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x33, 0x1A}); // i16x8.le_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x34, 0x1A}); // i16x8.le_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x35, 0x1A}); // i16x8.ge_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x36, 0x1A}); // i16x8.ge_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x37, 0x1A}); // i32x4.eq
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x38, 0x1A}); // i32x4.ne
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x39, 0x1A}); // i32x4.lt_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x3A, 0x1A}); // i32x4.lt_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x3B, 0x1A}); // i32x4.gt_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x3C, 0x1A}); // i32x4.gt_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x3D, 0x1A}); // i32x4.le_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x3E, 0x1A}); // i32x4.le_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x3F, 0x1A}); // i32x4.ge_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x40, 0x1A}); // i32x4.ge_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x4D, 0x1A}); // v128.not
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x4E, 0x1A}); // v128.and
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x4F, 0x1A}); // v128.andnot
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x50, 0x1A}); // v128.or
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x51, 0x1A}); // v128.xor
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x52, 0x1A}); // v128.bitselect
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x53, 0x1A}); // v128.any_true
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x60, 0x1A}); // i8x16.abs
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x61, 0x1A}); // i8x16.neg
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x62, 0x1A}); // i8x16.popcnt
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x63, 0x1A}); // i8x16.all_true
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x64, 0x1A}); // i8x16.bitmask
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0x6B, 0x1A}); // i8x16.shl
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0x6C, 0x1A}); // i8x16.shr_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0x6D, 0x1A}); // i8x16.shr_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x6E, 0x1A}); // i8x16.add
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x6F, 0x1A}); // i8x16.add_sat_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x70, 0x1A}); // i8x16.add_sat_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x71, 0x1A}); // i8x16.sub
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x72, 0x1A}); // i8x16.sub_sat_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x73, 0x1A}); // i8x16.sub_sat_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x76, 0x1A}); // i8x16.min_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x77, 0x1A}); // i8x16.min_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x78, 0x1A}); // i8x16.max_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x79, 0x1A}); // i8x16.max_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x7B, 0x1A}); // i8x16.avgr_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x80, 0x01, 0x1A}); // i16x8.abs
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x81, 0x01, 0x1A}); // i16x8.neg
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x83, 0x01, 0x1A}); // i16x8.all_true
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x84, 0x01, 0x1A}); // i16x8.bitmask
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0x8B, 0x01, 0x1A}); // i16x8.shl
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0x8C, 0x01, 0x1A}); // i16x8.shr_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0x8D, 0x01, 0x1A}); // i16x8.shr_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x8E, 0x01, 0x1A}); // i16x8.add
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x8F, 0x01, 0x1A}); // i16x8.add_sat_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x90, 0x01, 0x1A}); // i16x8.add_sat_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x91, 0x01, 0x1A}); // i16x8.sub
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x92, 0x01, 0x1A}); // i16x8.sub_sat_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x93, 0x01, 0x1A}); // i16x8.sub_sat_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x95, 0x01, 0x1A}); // i16x8.mul
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x96, 0x01, 0x1A}); // i16x8.min_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x97, 0x01, 0x1A}); // i16x8.min_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x98, 0x01, 0x1A}); // i16x8.max_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x99, 0x01, 0x1A}); // i16x8.max_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0x9B, 0x01, 0x1A}); // i16x8.avgr_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xA0, 0x01, 0x1A}); // i32x4.abs
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xA1, 0x01, 0x1A}); // i32x4.neg
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xA3, 0x01, 0x1A}); // i32x4.all_true
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xA4, 0x01, 0x1A}); // i32x4.bitmask
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0xAB, 0x01, 0x1A}); // i32x4.shl
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0xAC, 0x01, 0x1A}); // i32x4.shr_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0xAD, 0x01, 0x1A}); // i32x4.shr_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xAE, 0x01, 0x1A}); // i32x4.add
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xB1, 0x01, 0x1A}); // i32x4.sub
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xB5, 0x01, 0x1A}); // i32x4.mul
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xB6, 0x01, 0x1A}); // i32x4.min_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xB7, 0x01, 0x1A}); // i32x4.min_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xB8, 0x01, 0x1A}); // i32x4.max_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xB9, 0x01, 0x1A}); // i32x4.max_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xBA, 0x01, 0x1A}); // i32x4.dot_i16x8_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xC0, 0x01, 0x1A}); // i64x2.abs
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xC1, 0x01, 0x1A}); // i64x2.neg
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xC3, 0x01, 0x1A}); // i64x2.all_true
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xC4, 0x01, 0x1A}); // i64x2.bitmask
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0xCB, 0x01, 0x1A}); // i64x2.shl
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0xCC, 0x01, 0x1A}); // i64x2.shr_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x01, 0xFD, 0xCD, 0x01, 0x1A}); // i64x2.shr_u
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xCE, 0x01, 0x1A}); // i64x2.add
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xD1, 0x01, 0x1A}); // i64x2.sub
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xD5, 0x01, 0x1A}); // i64x2.mul
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xD6, 0x01, 0x1A}); // i64x2.eq
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xD7, 0x01, 0x1A}); // i64x2.ne
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xD8, 0x01, 0x1A}); // i64x2.lt_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xD9, 0x01, 0x1A}); // i64x2.gt_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xDA, 0x01, 0x1A}); // i64x2.le_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xDB, 0x01, 0x1A}); // i64x2.ge_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xF8, 0x01, 0x1A}); // i32x4.trunc_sat_f32x4_s
|
|
testMB({0xFD, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD, 0xF9, 0x01, 0x1A}); // i32x4.trunc_sat_f32x4_u
|
|
|
|
// clang-format on
|
|
}
|
|
}
|
|
|
|
void
|
|
run() override
|
|
{
|
|
using namespace test::jtx;
|
|
|
|
testGetDataHelperFunctions();
|
|
testWasmLib();
|
|
testBadWasm();
|
|
testWasmLedgerSqn();
|
|
|
|
testWasmFib();
|
|
testWasmSha();
|
|
testWasmB58();
|
|
|
|
testHFCost();
|
|
testEscrowWasmDN();
|
|
testFloat();
|
|
|
|
testCodecovWasm();
|
|
testDisabledFloat();
|
|
|
|
testWasmMemory();
|
|
testWasmTable();
|
|
testWasmProposal();
|
|
testWasmTrap();
|
|
testWasmWasi();
|
|
testWasmSectionCorruption();
|
|
|
|
testStartFunctionLoop();
|
|
testBadAlloc();
|
|
testBadAlign();
|
|
testReturnType();
|
|
testSwapBytes();
|
|
testManyParams();
|
|
testParameterType();
|
|
|
|
testOpcodes();
|
|
|
|
// perfTest();
|
|
}
|
|
};
|
|
|
|
BEAST_DEFINE_TESTSUITE(Wasm, app, xrpl);
|
|
|
|
} // namespace test
|
|
} // namespace xrpl
|