fix: script number overflow check for push_int#3392
fix: script number overflow check for push_int#3392apoelstra merged 2 commits intorust-bitcoin:masterfrom
Conversation
Pull Request Test Coverage Report for Build 11025652486Details
💛 - Coveralls |
|
Patch 1 and 2 need to be combined mate, otherwise they won't build individually. |
5a5dc84 to
48fc158
Compare
|
Squashed commits! |
48fc158 to
4491e04
Compare
tcharding
left a comment
There was a problem hiding this comment.
Thanks for your contribution, I had a play with it.
There was a problem hiding this comment.
Perhaps this function is cleaner if written like this?
/// Adds instructions to push an integer onto the stack.
///
/// Integers are encoded as little-endian signed-magnitude numbers, but there are dedicated
/// opcodes to push some small integers.
///
/// # Errors
///
/// Only errors if `data == i32::MIN` (CScriptNum cannot have value -2^31).
pub fn push_int(self, data: i32) -> Result<Builder, Error> {
if data == i32::MIN {
Err(Error::NumericOverflow)
}
else if data == -1 {
Ok(sef.push_opcode(OP_PUSHNUM_NEG1))
} else if data >= 0 {
Ok(self.push_uint(data as u32))
} else {
Ok(self.push_int_non_minimal(data.into()))
}
}Its up to you but I'd personally order the functions push_int, push_uint, and then push_int_non_minimal.
Also if we are touching these functions perhaps we should re-name the parameter, data does not convey much info. n is the name that jumps out at me but some folk don't like short names, is there any other conventional name we could use @apoelstra?
There was a problem hiding this comment.
That's a great retouch! I will reflect it when the new name of param is ready.
|
Thanks for sticking with this man! Sorry to be a nuisance but can you change the patch series again. We use a system whereby after review, if changes need to be made, one should rebase and redo the patch series putting review suggestions in the original patch where it was suggested. The aim being that the PR (patch series) is always a series of discreet steps to create the final state. A patch later in the series should not change things done in an earlier patch. This system is designed to optimize for reviewer time at the cost of developer time based on the observation that in open source projects reviewer time is much more scarce. And each patch should be a single discreet change, this makes it much easier to review, and more likely that reviewers will catch bugs. So looking at all changes in this PR together, one strategy to break it up might be:
|
tcharding
left a comment
There was a problem hiding this comment.
And some more little suggestions.
bitcoin/src/address/mod.rs
Outdated
There was a problem hiding this comment.
We could use push_uint here and not use unwrap
There was a problem hiding this comment.
This file is out of blockdata so cannot use push_uint
bitcoin/src/address/mod.rs
Outdated
bitcoin/src/blockdata/constants.rs
Outdated
There was a problem hiding this comment.
| .push_int(486604799) | |
| .unwrap() | |
| .push_uint(486604799) |
There was a problem hiding this comment.
Maybe some sort of code comment here with a reference if you have one to spare, I don't have one, only what I read Sanket write in the issue. No stress if you don't find one though.
There was a problem hiding this comment.
d6f28ca to
7f04560
Compare
|
No problem! Reflect suggestions and rearrange the patches. |
7f04560 to
4410577
Compare
|
Reviewed 44105778e9a6c9530d3bb140c61d1e010e1f8c88. The code looks good but I'm confused as to what the intended semantics are:
|
|
If "i32::MAX or below" means n <= |
We already have
It cannot, because |
|
I originally meant to make it private(used as a helper method for Do you mean n <= |
They will not be. What if you
What does this mean? The comparison is meaningful and can be implemented in Script. |
|
In Bitcoin core CScriptNum, it says
If the result overflows, it cannot be used in a subsequent numeric operation. Isn't the comparison(e.g. |
|
Yes, |
|
Oh sorry I didn't know that case. In that case, isn't |
|
Yes, somebody could just use |
|
I think it's just dangerous to allow Personally I don't think the conclusion is safe enough to prevent user from pushing the wrong integer, because if Or we may add new method like |
|
This all seems reasonable to me. But then I think we could call |
3f36913 to
034e99e
Compare
|
I've updated with some changes, which has the followings for what we want to achieve.
commit 8c7ab24f50ec667c0097d3e759f96f9baba7d336
|
034e99e to
8c7ab24
Compare
bitcoin/src/blockdata/constants.rs
Outdated
There was a problem hiding this comment.
In 1100de47bb893407bd2380433460085d4388c282:
We should just use unwrap here and make push_uint pub(super). In general I am suspicious of pub(in module) because it suggests there is some abstraction failure. In this case it's just to save an unwrap call which is guaranteed to be optimized away.
Alternately we can use push_int_unchecked
There was a problem hiding this comment.
I've removed push_uint and changed every push_int to push_int_unchecked!
There was a problem hiding this comment.
In 1100de47bb893407bd2380433460085d4388c282:
Why not call this method push_int_unchecked and have it take an i64? This will avoid a cast and avoid an entire method definition. Plus it could be pub and avoid any thinking about module visibilty.
There was a problem hiding this comment.
I couldn't come up with this idea as constantly change the code. Thanks for good catch!
25a71b7 to
c7067c8
Compare
|
c7067c88760f7d7a1d251e2ac5d6e04b56f687f5
|
tcharding
left a comment
There was a problem hiding this comment.
ACK c7067c88760f7d7a1d251e2ac5d6e04b56f687f5
acd4716 to
c7067c8
Compare
c7067c8 to
33edaf9
Compare
|
Rebased 33edaf9! |
apoelstra
left a comment
There was a problem hiding this comment.
ACK c7067c88760f7d7a1d251e2ac5d6e04b56f687f5 successfully ran local tests
…erflow a33bcd3 test: ensure push_int check i32::MIN of overflow error (Chris Hyunhum Cho) c9988ba refactor: use match for OP_N push in push_int_unchecked (Chris Hyunhum Cho) Pull request description: Follow up #3392 c9988ba - refactor `push_int_unchecked` with match expression for cleaner code(many thanks for tcharding #3407). a33bcd3 - ensure newly introduced safe `push_int` function as expected, testing if returns `Error::NumericOverflow` when `n` is `i32::MIN` ACKs for top commit: tcharding: ACK a33bcd3 apoelstra: ACK a33bcd3 successfully ran local tests Tree-SHA512: 14f19d37f35b47e148b40c5017f0270c534c136d86be0c061cb476e1693130c5fc1bfc45a6f7c75a473022490c5f4e061cbc02640b1a616619ae721116e3cd54
Fix the issue #1530. In the discussion of #1530, the suggested solution is to implement
ScriptInttype to embrace the various type of integer(i32, u32, i64, u64, i128, u128, isize, usize...) to support both script number and locktime number.However, as
push_locktimeandpush_sequenceimplemented, there’s no need to supportu32of lock time forpush_intanymore. Therefore, I’ve just changed the type of parameter toi32, and only check if it’si32::MIN(which overflows 4 bytes sign-magnitude integer).I also added push_uint method to use internally forpush_locktimeandpush_sequence, which have a dependency onpush_intmethod.UPDATE: also add
push_int_uncheckedfor those who want to push the integer out of range(and helper forpush_locktimeandpush_sequence, which has the same functionality of formerpush_int.