-
Notifications
You must be signed in to change notification settings - Fork 443
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
Fix Option pointer bug #570
Conversation
1f29702
to
2ca833a
Compare
2ca833a
to
69cd40e
Compare
Codecov Report
@@ Coverage Diff @@
## master #570 +/- ##
===========================================
- Coverage 82.47% 67.75% -14.73%
===========================================
Files 155 155
Lines 6820 6826 +6
===========================================
- Hits 5625 4625 -1000
- Misses 1195 2201 +1006
Continue to review full report at Codecov.
|
Thanks for fixing! This is exactly what I thought was wrong. :) |
This reverts commit 69cd40e.
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.
Thanks for the bug fix and clippy suggestion improvement.
@@ -545,4 +545,63 @@ mod tests { | |||
Ok(()) | |||
}) | |||
} | |||
|
|||
#[test] | |||
fn regression_test_for_issue_570() -> ink_env::Result<()> { |
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.
The entire test can be heavily simplified. You only need to push a (Option, i32)
tuple with values (None, 1)
to the contract storage and then read it again in the next step and assert that the first value is None
and the second value is 1
. Done.
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.
Or am I missing something?
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.
So that's a clever idea, I guess you thought the 1
would be written out to the first pointer and on the next pull_spread
we would try to read a Some(...)
there and fail. It doesn't work unfortunately because of this: push_spread
for Option
writes self.is_some() as u8
in the first ptr slot and increments the pointer. Hence on the next pull_spread
we immediately return the None
and continue pulling the i32
. So no failure would occur here.
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.
Using a tuple also doesn't simplify the test significantly, because for each tuple element the entire push_spread
recursion is called. So storage is basically overwritten until I introduce LazyCell
into the tuple. (Note that in my test only the Option
is pushed in step 2).
I mean the whole test could also be simplified way more drastically to something like
assert_eq!(ptr_after_pushing_none, ptr_after_pushing_some);
assert_eq!(ptr_after_pulling_none, ptr_after_pulling_some);
(I only thought of this now)
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.
Thanks for the elaboration!
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.
Thanks a lot for this fix! We will probably release an ink! 3.0-rc3 soon with it.
@@ -545,4 +545,63 @@ mod tests { | |||
Ok(()) | |||
}) | |||
} | |||
|
|||
#[test] | |||
fn regression_test_for_issue_570() -> ink_env::Result<()> { |
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.
Thanks for the elaboration!
Closes #568.
The bug was in the the implementation of
SpreadLayout
forOption
:On
push_spread
,clear_spread
,pull_spread
no further forwarding to the inner valuepush_spread
,clear_spread
,pull_spread
functions happened if theOption
wasNone
.This is problematic because these methods advance the ptr by one ‒ which happened if the
Option
wasSome(…)
. ForNone
it didn't happen, thus causing havoc for all objects that subsequently tried to push, pull or clear their content from storage.