Skip to content

Commit

Permalink
Merge pull request #647 from AntelopeIO/divmod_host_function_explicit
Browse files Browse the repository at this point in the history
explicitly handle inputs in `__divti3` and `__modti3` that result in UB overflow
  • Loading branch information
spoonincode authored Aug 28, 2024
2 parents da8c741 + 473d562 commit 9d65146
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
12 changes: 12 additions & 0 deletions libraries/chain/webassembly/compiler_builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ namespace eosio { namespace chain { namespace webassembly {

EOS_ASSERT(rhs != 0, arithmetic_exception, "divide by zero");

//force integer overflow to return dividend unchanged
if(lhs == std::numeric_limits<__int128>::min() && rhs == -1) {
*ret = lhs;
return;
}

lhs /= rhs;

*ret = lhs;
Expand Down Expand Up @@ -92,6 +98,12 @@ namespace eosio { namespace chain { namespace webassembly {

EOS_ASSERT(rhs != 0, arithmetic_exception, "divide by zero");

//force undefined behavior (due to lhs/rhs being an overflow) to return zero
if(lhs == std::numeric_limits<__int128>::min() && rhs == -1) {
*ret = 0;
return;
}

lhs %= rhs;
*ret = lhs;
}
Expand Down
6 changes: 6 additions & 0 deletions unittests/api_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

#include <contracts.hpp>
#include <test_contracts.hpp>
#include <test_wasts.hpp>
#include "test_cfd_transaction.hpp"


Expand Down Expand Up @@ -1487,6 +1488,11 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(compiler_builtins_tests, T, validating_testers) tr
// test test_ashrti3
CALL_TEST_FUNCTION( chain, "test_compiler_builtins", "test_ashrti3", {});

chain.produce_block();
chain.set_code( "testapi"_n, divmod_host_function_overflow_wast );
chain.produce_block();
CALL_TEST_FUNCTION( chain, "test_compiler_builtins", "", {}); //divmod_host_function_overflow_wast ignores action name

BOOST_REQUIRE_EQUAL( chain.validate(), true );
} FC_LOG_AND_RETHROW()

Expand Down
36 changes: 36 additions & 0 deletions unittests/contracts/test_wasts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1001,4 +1001,40 @@ static const char set_jumbo_row_wast[] = R"=====(
(drop (call $db_store_i64 (get_local $receiver) (get_local $receiver) (get_local $receiver) (i64.const 0) (i32.const 1) (i32.const 34603007)))
)
)
)=====";

static const char divmod_host_function_overflow_wast[] = R"=====(
(module
(import "env" "__divti3" (func $__divti3 (param $ret_ptr i32) (param $la i64) (param $ha i64) (param $lb i64) (param $hb i64)))
(import "env" "__modti3" (func $__modti3 (param $ret_ptr i32) (param $la i64) (param $ha i64) (param $lb i64) (param $hb i64)))
(memory $0 1)
(export "apply" (func $apply))
(func $apply (param $receiver i64) (param $account i64) (param $action_name i64)
(call $__divti3 (i32.const 8)
(i64.const 0) (i64.const 0x8000000000000000) ;; bytes: 0x00000000000000000000000000000080 (INT128_MIN)
(i64.const 0xffffffffffffffff) (i64.const 0xffffffffffffffff) ;; -1
)
;;should still be bytes 00000000000000000000000000000080
(if (i64.ne (i64.load (i32.const 8)) (i64.const 0)) (then
(unreachable)
))
(if (i64.ne (i64.load (i32.const 16)) (i64.const 0x8000000000000000)) (then
(unreachable)
))
(call $__modti3 (i32.const 8)
(i64.const 0) (i64.const 0x8000000000000000) ;; bytes: 0x00000000000000000000000000000080 (INT128_MIN)
(i64.const 0xffffffffffffffff) (i64.const 0xffffffffffffffff) ;; -1
)
;;should still be all 00s
(if (i64.ne (i64.load (i32.const 8)) (i64.const 0)) (then
(unreachable)
))
(if (i64.ne (i64.load (i32.const 16)) (i64.const 0)) (then
(unreachable)
))
)
)
)=====";

0 comments on commit 9d65146

Please sign in to comment.