Skip to content

Commit

Permalink
Merge pull request #371 from eosnetworkfoundation/oc_wasm_limits_fix
Browse files Browse the repository at this point in the history
tweak OC with WASM_LIMITS protocol feature
  • Loading branch information
spoonincode authored Jun 14, 2022
2 parents 0040dc5 + 75d679a commit da9acba
Showing 1 changed file with 19 additions and 2 deletions.
21 changes: 19 additions & 2 deletions libraries/chain/include/eosio/chain/webassembly/eos-vm-oc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ class eosvmoc_runtime : public eosio::chain::wasm_runtime_interface {
/**
* validate an in-wasm-memory array
* @tparam T
*
* When a pointer will be invalid we want to stop execution right here right now. This is accomplished by forcing a read from an address
* that must always be bad. A better approach would probably be to call in to a function that notes the invalid parameter and host function
* and then bubbles up a more useful error message; maybe some day. Prior to WASM_LIMITS the code just simply did a load from address 33MB via
* an immediate. 33MB was always invalid since 33MB was the most WASM memory you could have. Post WASM_LIMITS you theoretically could
* have up to 4GB, but we can't do a load from a 4GB immediate since immediates are limited to signed 32bit ranges.
*
* So instead access the first_invalid_memory_address which by its name will always be invalid. Or will it? No... it won't, since it's
* initialized to -1*64KB in the case WASM has _no_ memory! We actually cannot clamp first_invalid_memory_address to 0 during initialization
* in such a case since there is some historical funny business going on when end==0 (note how jle will _pass_ when end==0 & first_invalid_memory_address==0)
*
* So instead just bump first_invalid_memory_address another 64KB before accessing it. If it's -64KB it'll go to 0 which fails correctly in that case.
* If it's 4GB it'll go to 4GB+64KB which still fails too (there is an entire 8GB range of WASM memory set aside). There are other more straightforward
* ways of accomplishing this, but at least this approach has zero overhead (e.g. no additional register usage, etc) in the nominal case.
*/
template<typename T>
inline void* array_ptr_impl (size_t ptr, size_t length)
Expand All @@ -55,13 +69,16 @@ inline void* array_ptr_impl (size_t ptr, size_t length)

asm volatile("cmp %%gs:%c[firstInvalidMemory], %[End]\n"
"jle 1f\n"
"mov %%gs:(%[End]), %[Ptr]\n" // invalid pointer if out of range
"mov %%gs:%c[firstInvalidMemory], %[End]\n" // sets End with a known failing address
"add %[sizeOfOneWASMPage], %[End]\n" // see above comment
"mov %%gs:(%[End]), %[Ptr]\n" // loads from the known failing address
"1:\n"
"add %%gs:%c[linearMemoryStart], %[Ptr]\n"
: [Ptr] "+r" (ptr),
[End] "+r" (end)
: [linearMemoryStart] "i" (cb_full_linear_memory_start_segment_offset),
[firstInvalidMemory] "i" (cb_first_invalid_memory_address_segment_offset)
[firstInvalidMemory] "i" (cb_first_invalid_memory_address_segment_offset),
[sizeOfOneWASMPage] "i" (wasm_constraints::wasm_page_size)
: "cc"
);

Expand Down

0 comments on commit da9acba

Please sign in to comment.