Skip to content

Conversation

jonatack
Copy link
Member

@jonatack jonatack commented Aug 27, 2020

Fixes UBSan implicit-integer-sign-change issue per #19610 (comment).

Credit to Crypt-iQ for finding and reporting the issue and to vasild for the original review suggestion in #19590 (review).

Closes #19678.

fixes issue bitcoin#19678 UBSan implicit-integer-sign-change

Credit to Eugene (Crypt-iQ) for finding and reporting the issue
and to Vasil Dimov (vasild) for the original suggestion
@@ -425,7 +425,7 @@ class CInv
// Combined-message helper methods
bool IsGenTxMsg() const { return type == MSG_TX || type == MSG_WTX || type == MSG_WITNESS_TX; }

int type;
uint32_t type;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK on using a sized type here.
However, changing from signed to unsigned is, in principle, a P2P protocol change.
This needs to be carefully reviewed for potential unexpected by-effects.

@fanquake fanquake added the P2P label Aug 27, 2020
@maflcko
Copy link
Member

maflcko commented Aug 27, 2020

According to https://en.bitcoin.it/wiki/Protocol_documentation#Inventory_Vectors (section written in 2010 by "MagicalTux") this is unsigned. Though, our python tests also treat this as signed. https://btcinformation.org/en/developer-reference#inv doesn't say anything about signedness.

Would be good to at least update the python test framework and also add a p2p test.

@jonatack jonatack force-pushed the CInv-type-refactoring branch 2 times, most recently from ac8a804 to 9e05ed2 Compare August 27, 2020 14:02
@jonatack
Copy link
Member Author

jonatack commented Aug 27, 2020

Would be good to at least update the python test framework and also add a p2p test.

Updated the python test framework and added test coverage.

@jonatack jonatack force-pushed the CInv-type-refactoring branch 2 times, most recently from 1ab179b to 6c0f4ae Compare August 27, 2020 17:47
@practicalswift
Copy link
Contributor

Concept ACK

Thanks for fixing UBSan fuzzing finds!

@jonatack jonatack force-pushed the CInv-type-refactoring branch from 6c0f4ae to 1bb9a92 Compare August 27, 2020 19:05
@practicalswift
Copy link
Contributor

practicalswift commented Aug 28, 2020

@jonatack Just to confirm: if the test changes we're dropped in this change set (keeping only the changes to src/protocol.{cpp,h}) then all functional tests would still pass, right?

@jonatack
Copy link
Member Author

@jonasnick Just to confirm: if the test changes we're dropped in this change set (keeping only the changes to src/protocol.{cpp,h}) then all functional tests would still pass, right?

Right. I pushed the changes to src/protocol.{h/cpp} several times in other PR changesets (#19610, #19611) before dropping them, and the CI passes.

@jonatack jonatack force-pushed the CInv-type-refactoring branch from 1bb9a92 to 7bfc631 Compare August 28, 2020 08:44
@jnewbery
Copy link
Contributor

According to https://en.bitcoin.it/wiki/Protocol_documentation#Inventory_Vectors (section written in 2010 by "MagicalTux") this is unsigned. Though, our python tests also treat this as signed. https://btcinformation.org/en/developer-reference#inv doesn't say anything about signedness.

btcinformation.org does show this as uint32_t: https://btcinformation.org/en/developer-reference#data-messages. That was added by @harding to the bitcoin.org developer docs here: bitcoin-dot-org/Bitcoin.org@1634212#diff-693f5b3e9d88b97c899694c8d1656cbbR110

Note that even though comparing an int to a uint32_t causes a UBSan warning, it's not actually undefined behaviour: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#:~:text=%2Dfsanitize%3Dimplicit%2Dinteger%2D,the%20new%20value%20is%20negative. However, I think it's still worth changing this, so that we're always comparing / xor'ing a uint32_t with a uint32_t, so concept ACK.

@jonatack
Copy link
Member Author

Great links @jnewbery, thanks.

Note that even though comparing an int to a uint32_t causes a UBSan warning, it's not actually undefined behaviour: clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#:~:text=%2Dfsanitize%3Dimplicit%2Dinteger%2D,the%20new%20value%20is%20negative.

"-fsanitize=implicit-integer-sign-change: Implicit conversion between integer types, if that changes the sign of the value...issues caught by this sanitizer are not undefined behavior, but are often unintentional."

@jonatack jonatack force-pushed the CInv-type-refactoring branch from 7bfc631 to 7984c39 Compare August 28, 2020 18:13
@jonatack
Copy link
Member Author

jonatack commented Aug 28, 2020

Thanks everyone for your feedback. I wrote a few tests but they all covered the change to the CInv class in the test framework, not the CInv change in protocol.{h,cpp}, so I've simplified and removed them in the latest push.

@laanwj
Copy link
Member

laanwj commented Aug 29, 2020

Thanks for addressing the comments, the code changes look good to me now.

Copy link
Contributor

@vasild vasild left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 7984c39

All the values we ever assign to CInv::type are non-negative within the reach of a signed 32 bit integer. GetDataMsg is uint32_t and in some places we |= a variable of type uint32_t into CInv::type:

inv.type |= nFetchFlags;

So it makes sense to have CInv::type as uint32_t.

Actually serializing a signed integer in the way we do it is not portable, it just works because all platforms use two's complement, but that's not guaranteed.

@laanwj
Copy link
Member

laanwj commented Sep 2, 2020

All the values we ever assign to CInv::type are non-negative within the reach of a signed 32 bit integer. GetDataMsg is uint32_t and in some places we |= a variable of type uint32_t into CInv::type

Bitwise arithmetic should definitely use unsigned integers, good point.

Actually serializing a signed integer in the way we do it is not portable, it just works because all platforms use two's complement, but that's not guaranteed.

I thought this was already guaranteed in C++11, but no, apparently only C++20 will guarantee two's complement signed integers.

@laanwj
Copy link
Member

laanwj commented Sep 3, 2020

ACK 7984c39

@maflcko
Copy link
Member

maflcko commented Sep 3, 2020

ACK 7984c39 🌻

Show signature and timestamp

Signature:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

ACK 7984c39be11ca04460883365e1ae2a496aaa6c0e 🌻
-----BEGIN PGP SIGNATURE-----

iQGzBAEBCgAdFiEE+rVPoUahrI9sLGYTzit1aX5ppUgFAlwqrYAACgkQzit1aX5p
pUjtLAwAtfwkLzUyVHkPG+CsHcnD4C7PQgsfTFBMxOM9trXOHY299iYHJehs2jwr
j748j23g+pETizxSTTPal7FmbYGvmVrITJiLVfLtMeW+9vOoP59qzb1/mvxEWFWw
8hQnBJtUxYH1t8DxdWcVLew4jTlGyds2E6hGb09htsPam9LAxW+eUDynlwFXQgE1
HNxmk8K2mMLYoHeLidculEx2UcQFIH7GqFWDplFDpzSAruFneWqyg+V2LUqhCTpH
Jq/YFXupkfmHrySzWkJz3Ix2mGslNaxtqw18KnFFIc8Kx1qzZKOvloWIZCjvnCQt
GbWMZfSvvf1ALu44WX+dZLl6NtGU8x18bS0y6tkKrPyW51XyouCn7J3aOk03IcXn
3LizPJLA5DFf9jCILzLwoQLRhZbLAVsSoWIBVIyIIuoOrsbf2omAoxe13HoepQzK
a02g086odTrNRvKdwARXzC6tLEdgQHW4mJbZJLDCJ1Gz+qXJOla2tCIrieZq0Y8T
vC5hwFiZ
=81Qa
-----END PGP SIGNATURE-----

Timestamp of file with hash a72c948f27f3e6c7aa323c708d61eff780f8ac68076405b22c540f1cb6199d2f -

@laanwj laanwj merged commit bd60a9a into bitcoin:master Sep 3, 2020
@jonatack jonatack deleted the CInv-type-refactoring branch September 3, 2020 15:30
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Sep 3, 2020
…`, fix UBSan warning

7984c39 test framework: serialize/deserialize inv type as unsigned int (Jon Atack)
407175e p2p: change CInv::type from int to uint32_t (Jon Atack)

Pull request description:

  Fixes UBSan implicit-integer-sign-change issue per bitcoin#19610 (comment).

  Credit to Crypt-iQ for finding and reporting the issue and to vasild for the original review suggestion in bitcoin#19590 (review).

  Closes bitcoin#19678.

ACKs for top commit:
  laanwj:
    ACK 7984c39
  MarcoFalke:
    ACK 7984c39 🌻
  vasild:
    ACK 7984c39

Tree-SHA512: 59f3a75f40ce066ca6f0bb1927197254238302b4073af1574bdbfe6ed580876437be804be4e47d51467d604f0d9e3a5875159f7f2edbb2351fdb2bb9465100b5
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Feb 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

UBSan warning when fuzzing with -fsanitize=integer
7 participants