-
-
Notifications
You must be signed in to change notification settings - Fork 800
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat[test]: implement abi_decode
spec test
#4095
feat[test]: implement abi_decode
spec test
#4095
Conversation
simplify imports with import hypothesis as hp
the large + nested sarrays just end up producing contracts that break the contract size limit
|
||
# add, edit, delete, word, splice, flip | ||
possible_actions = "adwww" | ||
actions = draw(st.lists(st.sampled_from(possible_actions), max_size=MAX_MUTATIONS)) |
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 can also generate an empty list, no? Don't we want min_size=1
?
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.
We want to test valid payloads too, we don't have to mutate the payload
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.
ok, i assumed we'd test valid payloads separately. we could enmurate all type combinations up to certain depth
st_byte = st_any_byte | ||
|
||
# add, edit, delete, word, splice, flip | ||
possible_actions = "adwww" |
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.
we deliberately don't use the rest of the actions?
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.
Yea, I was going to clean it up a bit. The edit, splice and flip actions turned out to not be very useful.
|
||
|
||
@st.composite | ||
def _mutate(draw, payload, max_mutations=MAX_MUTATIONS): |
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.
max_mutations
unused
static_leaf_ctors = [t for t in leaf_ctors if t._is_prim_word] | ||
dynamic_leaf_ctors = [BytesT, StringT] | ||
|
||
MAX_MUTATIONS = 33 |
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.
what is the reasoning behind using 33?
why is it ok to use 33 for all payloads, irrespective of their lengths? ie why do we assume this works well both for short and long payloads?
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.
It's about editing, you can add or delete one word (plus change)
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.
we bias towards the w
action, which is word-level
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.
overall, i'm not sure about the byte-level mutation. if it happens on the length
word, it will likely create an invalid length. if it happens on a pointer, it will likely create an invalid pointer (eg points to a too large address)
given the fairly low MAX_MUTATIONS
if a bad byte mutation happens, I think there's a low probability of offsetting it with a "good" mutation
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.
like normal fuzzers do it on this level, but i think that the mutation depth there is much higher
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.
i think it's mostly useful for editing the "data" portion of the payload, like it produces off-by-ones (expected length is 32 but data is only actually 31)
|
||
if t in (BytesT, StringT): | ||
# arbitrary max_value | ||
bound = draw(st.integers(min_value=1, max_value=1024)) |
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.
isn't 1024 unnecessarily large so it just slows down the tests? what cases might not be covered by eg 512?
i think that for the sake of completeness, we should also test with dirty memory let's consider that a ptr points outside the buffer to we currently only test for b) and require that the spec matches the implementation the spec should always raise when ptr points outside the buffer. but what if the implementation doesn't revert when pointing outside the buffer to dirty memory? |
ret.pop(ix) | ||
elif action == "w": | ||
# splice word | ||
st_uint256 = st.integers(min_value=0, max_value=2**256 - 1) |
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.
i'm not sure how useful this range is. the interesting values will be on it's boundaries but we can sample those for "cheaper"
in most cases we'll just sample some gigantic random number and i'd argue it will just hit the same code path each time (and for ptrs will mostly likely just oog)
i think it's important to include structs - one of the original errors was incorrect validation of structs within dynarrays |
I mean structs share the same code path as tuples, but with named fields in the front-end. I don't think we are missing much by not including them |
we skip them for dynarrays, right? |
Ah right, those are disallowed by the language semantics. Ok let's add them |
abi_decode
spec test
What I did
add a spec-based differential fuzzer test for
abi_decode
How I did it
How to verify it
Commit message
Description for the changelog
Cute Animal Picture