-
Notifications
You must be signed in to change notification settings - Fork 37.8k
Replace remaining sprintf with snprintf #9867
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
Conversation
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.
utACK.
ACK d9b6b87 |
src/uint256.cpp
Outdated
@@ -22,7 +22,7 @@ std::string base_blob<BITS>::GetHex() const | |||
{ | |||
char psz[sizeof(data) * 2 + 1]; | |||
for (unsigned int i = 0; i < sizeof(data); i++) | |||
sprintf(psz + i * 2, "%02x", data[sizeof(data) - i - 1]); | |||
snprintf(psz + i * 2, 3, "%02x", data[sizeof(data) - i - 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.
This is a little bit sketchy. Could it not safely be 2 here, not 3?
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.
NUL term needs a 3rd byte.
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.
For others http://www.cplusplus.com/reference/cstdio/snprintf/
A terminating null character is automatically appended after the content written.
Hence, 2 hex characters + 1 null character.
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 correct, and it's also why snprintf isn't an especially safe function call. (replaces one class of issue with another more subtle one)
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 correct, and it's also why snprintf isn't an especially safe function call. (replaces one class of issue with another more subtle one)
Indeed, that's why we never use it. The go-to function we have for this is "strprintf". However, it's kind of high overhead for formatting two hex characters. Especially as this function is called a lot.
I'll just replace this with use of HexDigit
instead.
Concept ACK for general sanity, though I'm pretty sure there is no reason we should go out of our way to support libcs that are deliberately broken. |
Somewhat tend to agree, though there is something to be said for deprecating unsafe functions that have caused so much pain since the 80's. They do the same with system calls, trying to keep the API (anda attack surface) as minimalist as possible. |
d9b6b87
to
30dc477
Compare
Force-pushed into two commits:
|
src/uint256.cpp
Outdated
static const char *hex_chars = "0123456789abcdef"; | ||
std::string retval; | ||
retval.reserve(sizeof(data) * 2); | ||
for (unsigned int i = 0; i < sizeof(data); i++) { |
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.
why not size_t
?
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.
Meh. For loop counters it's generally enough to use a 32-bit type. Especially if you know you're only going to count to 64, ever.
src/uint256.cpp
Outdated
for (unsigned int i = 0; i < sizeof(data); i++) { | ||
uint8_t value = data[sizeof(data) - i - 1]; | ||
retval.push_back(hex_chars[value >> 4]); | ||
retval.push_back(hex_chars[value & 0xf]); |
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.
edit: fail
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.
But incorrect.
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.
nit: maybe emplace rather than push (potentially saves an initialization)
@dcousens can you not delete your feedback? I had to dig in my emails to see that I wasn't repeating your feedback.
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.
Do you really think there's anything to be gained by emplacing a char? I'd say something has to be really wrong for that to make a difference.
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.
Anyhow I have a better solution based on reverse_iterator coming, so no need to discuss this further.
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 pretty sure that the copy constructor and move constructor for a char are the same, so emplace wouldn't make a difference.
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.
@JeremyRubin I made a woefully incorrect suggestion in regards to the bitmasking.
retval.push_back(hex_chars[value & 0xf0]);
retval.push_back(hex_chars[value & 0x0f]);
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.
@dcousens no worries we all have our dumb moments.
@@ -20,10 +20,15 @@ base_blob<BITS>::base_blob(const std::vector<unsigned char>& vch) | |||
template <unsigned int BITS> | |||
std::string base_blob<BITS>::GetHex() const |
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.
Possibly we could even use HexStr here with a reverse_iterator, though I don't know how to do that for a C-style array. All the variations I can think of are much worse than just replicating this functionality here.
Edit: found it out, it's simple!
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.
#include "stdio.h"
#include <iterator>
int main() {
char a[2] = {'a', 'b'};
auto start = std::reverse_iterator<char *>(&a[2]);
auto end = std::reverse_iterator<char *>(&a[0]);
while (start != end)
printf("%c", *(start++));
}
Outputs:
ba
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.
Yes, thanks, I'm aware, see the new version of this patch.
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.
ha -- and here I was thinking you coded it after I commented and I was like "wow, @laanwj is a god amongst men in code response times" ;)
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.
Yes, I implemented it in minus 3 minutes! Truly godlike :-)
Instead of calling sprintf for every byte, format the hex bytes ourselves by help of HexStr and a reverse_iterator.
Use of `sprintf` is seen as a red flag as many of its uses are insecure. OpenBSD warns about it while compiling, and some modern platforms, e.g. [cloudlibc from cloudabi](https://github.com/NuxiNL/cloudlibc) don't even provide it anymore. Although our uses of these functions are secure, it can't hurt to replace them anyway. There are only 3 occurences left, all in the tests.
30dc477
to
19cafc6
Compare
There you go, a one-liner now. |
utACK 19cafc6 |
utACK 19cafc6 |
utACK |
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.
re-utACK.
utACK 19cafc6 |
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.
utACK 19cafc6
19cafc6 test: Replace remaining sprintf with snprintf (Wladimir J. van der Laan) 0a17714 uint256: replace sprintf with HexStr and reverse-iterator (Wladimir J. van der Laan) Tree-SHA512: 2ba1dd4d25e1cbfff4d67b2f483448aa7c34ab5c799cddd48ba5826e5fa6df425abe35e244aaf4c52db9fccfb4d2a25a14bb4597bf9d1fce95991f270da6bb26
Additional dbwrapper tests Cherry-picked from the following upstream PRs: - bitcoin/bitcoin#7992 - bitcoin/bitcoin#9867 - Only the commit affecting dbwrapper tests - bitcoin/bitcoin#9610 - Only the change affecting dbwrapper tests - bitcoin/bitcoin#10844
19cafc6 test: Replace remaining sprintf with snprintf (Wladimir J. van der Laan) 0a17714 uint256: replace sprintf with HexStr and reverse-iterator (Wladimir J. van der Laan) Tree-SHA512: 2ba1dd4d25e1cbfff4d67b2f483448aa7c34ab5c799cddd48ba5826e5fa6df425abe35e244aaf4c52db9fccfb4d2a25a14bb4597bf9d1fce95991f270da6bb26
19cafc6 test: Replace remaining sprintf with snprintf (Wladimir J. van der Laan) 0a17714 uint256: replace sprintf with HexStr and reverse-iterator (Wladimir J. van der Laan) Tree-SHA512: 2ba1dd4d25e1cbfff4d67b2f483448aa7c34ab5c799cddd48ba5826e5fa6df425abe35e244aaf4c52db9fccfb4d2a25a14bb4597bf9d1fce95991f270da6bb26
19cafc6 test: Replace remaining sprintf with snprintf (Wladimir J. van der Laan) 0a17714 uint256: replace sprintf with HexStr and reverse-iterator (Wladimir J. van der Laan) Tree-SHA512: 2ba1dd4d25e1cbfff4d67b2f483448aa7c34ab5c799cddd48ba5826e5fa6df425abe35e244aaf4c52db9fccfb4d2a25a14bb4597bf9d1fce95991f270da6bb26
Lint fixes Fixes most lints currently reported by `test/lint/lint-all.sh`. Includes changes cherry-picked from the following upstream PRs: - bitcoin/bitcoin#8700 - bitcoin/bitcoin#8840 - bitcoin/bitcoin#9867 - We backported the second commit in #3146 - bitcoin/bitcoin#10771 - bitcoin/bitcoin#11394 - bitcoin/bitcoin#11649 - bitcoin/bitcoin#17329 - bitcoin/bitcoin#19258
bc3d3fa Add testcase to simulate bitcoin schema in leveldb (MapleLaker) 4f15155 Verify DBWrapper iterators are taking snapshots (Matt Corallo) 36b407e test: Replace remaining sprintf with snprintf (Wladimir J. van der Laan) e8cb38a Add test for dbwrapper iterators with same-prefix keys. (Matt Corallo) 4a4ddb8 test: Add more thorough test for dbwrapper iterators I made a silly mistake in a database wrapper where keys were sorted by char instead of uint8_t. As x86 char is signed the sorting for the block index database was messed up, resulting in a segfault due to missing records. (Wladimir J. van der Laan) 109446f chain: Add assertion in case of missing records in index db (Wladimir J. van der Laan) Pull request description: Back ported the following PRs from upstream (adaptations were needed because we aren't obfuscating the db): * bitcoin#7992. * bitcoin#9867. * bitcoin#11422. * bitcoin#17206 ACKs for top commit: random-zebra: Nice! ACK bc3d3fa Tree-SHA512: ebd811d7ee0d970247ceec2624e524df7611274f36ef7c0252712ebf247828ee091dcc6872585271fac3d7846127a997a856d7cd72eb20425e06213207ff1c7a
Use of
sprintf
is seen as a red flag as many of its uses are insecure. OpenBSD warns about it while compiling, and some modern platforms, e.g. cloudlibc from cloudabi don't even provide it anymore.Although our uses of these functions are secure, it can't hurt to replace them anyway. There are only 4 occurences of which 3 in the tests.