-
Notifications
You must be signed in to change notification settings - Fork 346
Implement dynamic memory and fix out of bounds issues #607
Implement dynamic memory and fix out of bounds issues #607
Conversation
@@ -324,14 +324,14 @@ func (function *SNativeFunctionDescription) NArgs() int { | |||
return len(function.Args) | |||
} | |||
|
|||
func arg(name string, abiTypeName abi.TypeName) abi.Arg { | |||
func abiArg(name string, abiTypeName abi.TypeName) abi.Arg { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was renamed to be consistent with ret below
return abi.Arg{ | ||
Name: name, | ||
TypeName: abiTypeName, | ||
} | ||
} | ||
|
||
func ret(name string, abiTypeName abi.TypeName) abi.Return { | ||
func abiReturn(name string, abiTypeName abi.TypeName) abi.Return { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was renamed so as to not clash with the local variable ret
in the vm package
34afb3c
to
afb7867
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM; important conservative improvement to adjust for modern compiler behaviour (which assumes dynamic, unlimited memory allocation) and improving the robustness of the memory implementation. Some considerations:
- we will now always copy memory on reading (before the copy behaviour was less obvious); requiring explicit write, suffering minor (possible) performance cost in exchange for code clarity and better encapsulation; possible optimisations can be considered on top of the interface at later stage;
memErr
is "ignored" because I asked for it to be ignored at this point; rather we should evaluate more structure in VM errors at later date;- the dynamic memory allocation brings back to the foreground that we need refine our use of the gaslimit during execution, as this adds weight to this possible attack vector.
please fmt |
I have just amended the commit to debug log the
func (st *Stack) Push(d Word256) {
st.useGas(GasStackOp)
if st.ptr == cap(st.data) {
st.setErr(ErrDataStackOverflow)
return
}
st.data[st.ptr] = d
st.ptr++
}
// ...
func LeftPadWord256(bz []byte) (word Word256) {
copy(word[32-len(bz):], bz)
return
} For cases like this (where we want a copy somewhere downstream) we could provide a function on the
|
CLI tests pass for me at this version: https://github.com/monax/cli/blob/6a14d0cf2e890be98d9e35f4d26dd29d5292f793/Makefile#L92 |
Further tests in monax/cli also pass locally for me. |
Implement dynamic memory and fix out of bounds issues
This PR introduces a dynamic memory implementation that satisfies the assumption (by Solidity) that memory will be dynamically allocated at the memory boundary when an
MSTORE
writes to the memory boundary provided byMSIZE
.The Solidity compiler assumes that memory will be dynamically allocated at the current memory upper bounds (as reported by
MSIZE
) if anMSTORE
operation tries to write to it. I believe the reason for this behaviour is that it is an easy way to guarantee that a portion a of memory will be unused (since it has not yet been allocated). Obviously this only works if the EVM environment will dynamically allocate that memory for you. This PR implements this in Burrow.For reference, the Solidity assumption around object creation is encoded in the Solidity compiler here: https://github.com/ethereum/solidity/blob/develop/libsolidity/codegen/ExpressionCompiler.cpp#L842-L851
And you can see the dynamic memory allocation in go-ethereum here: https://github.com/ethereum/go-ethereum/blob/master/core/vm/interpreter.go#L152-L173 . Where the memory size is just the mstore offset + one word calculated here: https://github.com/ethereum/go-ethereum/blob/master/core/vm/memory_table.go#L49-L51.
I have taken a simpler approach of growing the memory on a
Write
operation up to a configurable bounds. I make use of the underlying slice implementation in Go to efficiently grow arrays. This PR includes:Memory
interface to encapsulate memory operationsmemoryProvider
argument toNewVM
Memory
objectsubslice
function simply wasn't fit for purposeI have verified that this fixes the following issues:
fixes #474
fixes #258
fixes #300 (could not use exactly the same code)