Skip to content

Commit e641ec6

Browse files
authored
Merge pull request #103 from eosnetworkfoundation/wasm_test_grabbag
grab bag of misc WASM unit tests for old defects
2 parents 79b1f0c + dd172bf commit e641ec6

3 files changed

Lines changed: 397 additions & 0 deletions

File tree

unittests/api_tests.cpp

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,6 +1968,180 @@ BOOST_FIXTURE_TEST_CASE(crypto_tests, TESTER) { try {
19681968
BOOST_REQUIRE_EQUAL( validate(), true );
19691969
} FC_LOG_AND_RETHROW() }
19701970

1971+
/*************************************************************************************
1972+
* memory_tests test case
1973+
*************************************************************************************/
1974+
static const char memcpy_pass_wast[] = R"======(
1975+
(module
1976+
(import "env" "memcpy" (func $memcpy (param i32 i32 i32) (result i32)))
1977+
(import "env" "eosio_assert" (func $eosio_assert (param i32 i32)))
1978+
(memory 1)
1979+
(func (export "apply") (param i64 i64 i64)
1980+
(i64.store (i32.const 0) (i64.const 0x8877665544332211))
1981+
(call $eosio_assert (i32.eq (call $memcpy (i32.const 65535) (i32.const 0) (i32.const 1)) (i32.const 65535)) (i32.const 128))
1982+
(call $eosio_assert (i64.eq (i64.load (i32.const 65528)) (i64.const 0x1100000000000000)) (i32.const 256))
1983+
(drop (call $memcpy (i32.const 8) (i32.const 7) (i32.const 1)))
1984+
(drop (call $memcpy (i32.const 7) (i32.const 8) (i32.const 1)))
1985+
)
1986+
(data (i32.const 128) "expected memcpy to return 65535")
1987+
(data (i32.const 256) "expected memcpy to write one byte")
1988+
)
1989+
)======";
1990+
1991+
static const char memcpy_overlap_wast[] = R"======(
1992+
(module
1993+
(import "env" "memcpy" (func $memcpy (param i32 i32 i32) (result i32)))
1994+
(memory 1)
1995+
(func (export "apply") (param i64 i64 i64)
1996+
(drop (call $memcpy (i32.const 16) (i32.wrap/i64 (get_local 2)) (i32.const 8)))
1997+
)
1998+
)
1999+
)======";
2000+
2001+
static const char memcpy_past_end_wast[] = R"======(
2002+
(module
2003+
(import "env" "memcpy" (func $memcpy (param i32 i32 i32) (result i32)))
2004+
(memory 1)
2005+
(func (export "apply") (param i64 i64 i64)
2006+
(drop (call $memcpy (i32.const 65535) (i32.const 0) (i32.const 2)))
2007+
)
2008+
)
2009+
)======";
2010+
2011+
static const char memmove_pass_wast[] = R"======(
2012+
(module
2013+
(import "env" "memmove" (func $memmove (param i32 i32 i32) (result i32)))
2014+
(import "env" "eosio_assert" (func $eosio_assert (param i32 i32)))
2015+
(memory 1)
2016+
(func $fillmem (param i32 i32)
2017+
(loop
2018+
(i32.store8 (get_local 0) (get_local 1))
2019+
(set_local 1 (i32.sub (get_local 1) (i32.const 1)))
2020+
(set_local 0 (i32.add (get_local 0) (i32.const 1)))
2021+
(br_if 0 (get_local 1))
2022+
)
2023+
)
2024+
(func $checkmem (param i32 i32 i32)
2025+
(loop
2026+
(call $eosio_assert (i32.eq (i32.load8_u (get_local 0)) (get_local 1)) (get_local 2))
2027+
(set_local 1 (i32.sub (get_local 1) (i32.const 1)))
2028+
(set_local 0 (i32.add (get_local 0) (i32.const 1)))
2029+
(br_if 0 (get_local 1))
2030+
)
2031+
)
2032+
(func (export "apply") (param i64 i64 i64)
2033+
(i64.store (i32.const 0) (i64.const 0x8877665544332211))
2034+
(call $eosio_assert (i32.eq (call $memmove (i32.const 65535) (i32.const 0) (i32.const 1)) (i32.const 65535)) (i32.const 128))
2035+
(call $eosio_assert (i64.eq (i64.load (i32.const 65528)) (i64.const 0x1100000000000000)) (i32.const 256))
2036+
2037+
(call $fillmem (i32.const 8) (i32.const 128))
2038+
(drop (call $memmove (i32.const 64) (i32.const 8) (i32.const 128)))
2039+
(call $checkmem (i32.const 64) (i32.const 128) (i32.const 384))
2040+
2041+
(call $fillmem (i32.const 8) (i32.const 128))
2042+
(drop (call $memmove (i32.const 8) (i32.const 8) (i32.const 128)))
2043+
(call $checkmem (i32.const 8) (i32.const 128) (i32.const 512))
2044+
2045+
(call $fillmem (i32.const 64) (i32.const 128))
2046+
(drop (call $memmove (i32.const 8) (i32.const 64) (i32.const 128)))
2047+
(call $checkmem (i32.const 8) (i32.const 128) (i32.const 640))
2048+
)
2049+
(data (i32.const 128) "expected memmove to return 65535")
2050+
(data (i32.const 256) "expected memmove to write one byte")
2051+
(data (i32.const 384) "memmove overlap dest above src")
2052+
(data (i32.const 512) "memmove overlap exact")
2053+
(data (i32.const 640) "memmove overlap src above dst")
2054+
)
2055+
)======";
2056+
2057+
static const char memcmp_pass_wast[] = R"======(
2058+
(module
2059+
(import "env" "memcmp" (func $memcmp (param i32 i32 i32) (result i32)))
2060+
(import "env" "eosio_assert" (func $eosio_assert (param i32 i32)))
2061+
(memory 1)
2062+
(func (export "apply") (param i64 i64 i64)
2063+
(call $eosio_assert (i32.eq (call $memcmp (i32.const 65535) (i32.const 65535) (i32.const 1)) (i32.const 0)) (i32.const 128))
2064+
(call $eosio_assert (i32.eq (call $memcmp (i32.const 0) (i32.const 2) (i32.const 3)) (i32.const 0)) (i32.const 256))
2065+
(call $eosio_assert (i32.eq (call $memcmp (i32.const 0) (i32.const 2) (i32.const 6)) (i32.const -1)) (i32.const 384))
2066+
(call $eosio_assert (i32.eq (call $memcmp (i32.const 2) (i32.const 0) (i32.const 6)) (i32.const 1)) (i32.const 512))
2067+
)
2068+
(data (i32.const 0) "abababcdcdcd")
2069+
(data (i32.const 128) "memcmp at end of memory")
2070+
(data (i32.const 256) "memcmp overlap eq1")
2071+
(data (i32.const 384) "memcmp overlap <")
2072+
(data (i32.const 512) "memcmp overlap >")
2073+
)
2074+
)======";
2075+
2076+
static const char memset_pass_wast[] = R"======(
2077+
(module
2078+
(import "env" "memset" (func $memset (param i32 i32 i32) (result i32)))
2079+
(import "env" "eosio_assert" (func $eosio_assert (param i32 i32)))
2080+
(memory 1)
2081+
(func (export "apply") (param i64 i64 i64)
2082+
(call $eosio_assert (i32.eq (call $memset (i32.const 65535) (i32.const 0xCC) (i32.const 1)) (i32.const 65535)) (i32.const 128))
2083+
(call $eosio_assert (i64.eq (i64.load (i32.const 65528)) (i64.const 0xCC00000000000000)) (i32.const 256))
2084+
)
2085+
(data (i32.const 128) "expected memset to return 65535")
2086+
(data (i32.const 256) "expected memset to write one byte")
2087+
)
2088+
)======";
2089+
2090+
BOOST_FIXTURE_TEST_CASE(memory_tests, TESTER) {
2091+
produce_block();
2092+
create_accounts( { "memcpy"_n, "memcpy2"_n, "memcpy3"_n, "memmove"_n, "memcmp"_n, "memset"_n } );
2093+
set_code( "memcpy"_n, memcpy_pass_wast );
2094+
set_code( "memcpy2"_n, memcpy_overlap_wast );
2095+
set_code( "memcpy3"_n, memcpy_past_end_wast );
2096+
set_code( "memmove"_n, memmove_pass_wast );
2097+
set_code( "memcmp"_n, memcmp_pass_wast );
2098+
set_code( "memset"_n, memset_pass_wast );
2099+
auto pushit = [&](name acct, name act) {
2100+
signed_transaction trx;
2101+
trx.actions.push_back({ { {acct, config::active_name} }, acct, act, bytes()});
2102+
set_transaction_headers(trx);
2103+
trx.sign(get_private_key(acct, "active"), control->get_chain_id());
2104+
push_transaction(trx);
2105+
};
2106+
pushit("memcpy"_n, name());
2107+
pushit("memcpy2"_n, name(0));
2108+
pushit("memcpy2"_n, name(8));
2109+
BOOST_CHECK_THROW(pushit("memcpy2"_n, name(12)), overlapping_memory_error);
2110+
BOOST_CHECK_THROW(pushit("memcpy2"_n, name(16)), overlapping_memory_error);
2111+
BOOST_CHECK_THROW(pushit("memcpy2"_n, name(20)), overlapping_memory_error);
2112+
BOOST_CHECK_THROW(pushit("memcpy3"_n, name()), wasm_execution_error);
2113+
pushit("memcpy2"_n, name(24));
2114+
2115+
pushit("memmove"_n, name());
2116+
pushit("memcmp"_n, name());
2117+
pushit("memset"_n, name());
2118+
}
2119+
2120+
static const char cstr_wast[] = R"======(
2121+
(module
2122+
(import "env" "eosio_assert" (func $eosio_assert (param i32 i32)))
2123+
(memory 1)
2124+
(func (export "apply") (param i64 i64 i64)
2125+
(call $eosio_assert (i32.const 1) (i32.const 65534))
2126+
)
2127+
(data (i32.const 65535) "x")
2128+
)
2129+
)======";
2130+
2131+
BOOST_FIXTURE_TEST_CASE(cstr_tests, TESTER) {
2132+
produce_block();
2133+
create_accounts( { "cstr"_n } );
2134+
set_code( "cstr"_n, cstr_wast );
2135+
auto pushit = [&](name acct, name act) {
2136+
signed_transaction trx;
2137+
trx.actions.push_back({ { {acct, config::active_name} }, acct, act, bytes()});
2138+
set_transaction_headers(trx);
2139+
trx.sign(get_private_key(acct, "active"), control->get_chain_id());
2140+
push_transaction(trx);
2141+
};
2142+
pushit("cstr"_n, name());
2143+
}
2144+
19712145
/*************************************************************************************
19722146
* print_tests test case
19732147
*************************************************************************************/

unittests/contracts/test_wasts.hpp

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,3 +876,118 @@ static const std::vector<uint8_t> varuint_memory_flags{
876876
0x07, 0x09, 0x01, 0x05, 'a', 'p', 'p', 'l', 'y', 0x00, 0x00, // exports
877877
0x0a, 0x04, 0x01, 0x02, 0x00, 0x0b // code
878878
};
879+
880+
static const char zero_memory_do_nothing[] = R"=====(
881+
(module
882+
(export "apply" (func $apply))
883+
(memory $0 0)
884+
(func $apply (param i64) (param i64) (param i64)
885+
)
886+
)
887+
)=====";
888+
889+
static const char zero_memory_load[] = R"=====(
890+
(module
891+
(export "apply" (func $apply))
892+
(memory $0 0)
893+
(func $apply (param i64) (param i64) (param i64)
894+
(drop (i64.load (i32.const 0)))
895+
)
896+
)
897+
)=====";
898+
899+
static const char zero_memory_intrinsic[] = R"=====(
900+
(module
901+
(export "apply" (func $apply))
902+
(import "env" "read_transaction" (func $read_transaction (param i32 i32) (result i32)))
903+
(memory $0 0)
904+
(func $apply (param i64) (param i64) (param i64)
905+
(drop (call $read_transaction (i32.const 16) (i32.const 0)))
906+
)
907+
)
908+
)=====";
909+
910+
static const char zero_memory_grow[] = R"=====(
911+
(module
912+
(export "apply" (func $apply))
913+
(memory $0 0)
914+
(func $apply (param i64) (param i64) (param i64)
915+
(drop (grow_memory (i32.const 1)))
916+
(drop (i64.load (i32.const 0)))
917+
)
918+
)
919+
)=====";
920+
921+
static const char zero_memory_grow_hi[] = R"=====(
922+
(module
923+
(export "apply" (func $apply))
924+
(memory $0 0)
925+
(func $apply (param i64) (param i64) (param i64)
926+
(drop (grow_memory (i32.const 1)))
927+
(drop (i64.load (i32.const 70000)))
928+
)
929+
)
930+
)=====";
931+
932+
static const char exit_in_start_wast[] = R"=====(
933+
(module
934+
(import "env" "abort" (func $abort))
935+
(import "env" "eosio_exit" (func $eosio_exit (param i32)))
936+
(export "apply" (func $apply))
937+
(start $dothedew)
938+
(func $dothedew
939+
(call $eosio_exit (i32.const 0))
940+
)
941+
(func $apply (param $0 i64) (param $1 i64) (param $2 i64)
942+
(call $abort)
943+
)
944+
)
945+
)=====";
946+
947+
static const char negative_memory_grow_wast[] = R"=====(
948+
(module
949+
(memory 1)
950+
(func (export "apply") (param i64 i64 i64)
951+
(block
952+
(drop (grow_memory (i32.const 1)))
953+
(i32.eq (grow_memory (i32.const -1)) (i32.const 2))
954+
(br_if 0)
955+
(unreachable)
956+
)
957+
(block
958+
(drop (grow_memory (i32.const 2)))
959+
(i32.eq (grow_memory (i32.const -3)) (i32.const 3))
960+
(br_if 0)
961+
(unreachable)
962+
)
963+
(block
964+
(drop (grow_memory (i32.const 1)))
965+
(i32.store (i32.const 0) (i32.const -1))
966+
(i32.store (i32.const 65532) (i32.const -1))
967+
(grow_memory (i32.const -1))
968+
(grow_memory (i32.const 1))
969+
(i32.and (i32.eq (i32.load (i32.const 0)) (i32.const 0))
970+
(i32.eq (i32.load (i32.const 65532)) (i32.const 0)))
971+
(br_if 0)
972+
(unreachable)
973+
)
974+
(block
975+
(i32.eq (grow_memory (i32.const -2)) (i32.const -1))
976+
(br_if 0)
977+
(unreachable)
978+
)
979+
)
980+
)
981+
)=====";
982+
983+
static const char negative_memory_grow_trap_wast[] = R"=====(
984+
(module
985+
(memory 1)
986+
(func (export "apply") (param i64 i64 i64)
987+
(block
988+
(drop (grow_memory (i32.const -1)))
989+
(drop (i32.load (i32.const 0)))
990+
)
991+
)
992+
)
993+
)=====";

0 commit comments

Comments
 (0)