Skip to content

Conversation

laanwj
Copy link
Member

@laanwj laanwj commented Feb 26, 2017

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.

Copy link
Contributor

@gmaxwell gmaxwell left a comment

Choose a reason for hiding this comment

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

utACK.

@paveljanik
Copy link
Contributor

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]);
Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor

@dcousens dcousens Feb 27, 2017

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.

Copy link
Contributor

@gmaxwell gmaxwell Feb 27, 2017

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)

Copy link
Member Author

@laanwj laanwj Feb 27, 2017

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.

@TheBlueMatt
Copy link
Contributor

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.

@laanwj
Copy link
Member Author

laanwj commented Feb 27, 2017

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.

@laanwj
Copy link
Member Author

laanwj commented Feb 27, 2017

Force-pushed into two commits:

  • uint256: replace use of sprintf with per-digit hex conversion
  • test: Replace remaining sprintf with snprintf

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++) {
Copy link
Contributor

Choose a reason for hiding this comment

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

why not size_t?

Copy link
Member Author

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]);
Copy link
Contributor

@dcousens dcousens Feb 27, 2017

Choose a reason for hiding this comment

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

edit: fail

Copy link
Member Author

Choose a reason for hiding this comment

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

But incorrect.

Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Member Author

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.

Copy link
Member

@sipa sipa Feb 27, 2017

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.

Copy link
Contributor

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]);

Copy link
Member Author

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
Copy link
Member Author

@laanwj laanwj Feb 27, 2017

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!

Copy link
Contributor

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

Copy link
Member Author

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.

Copy link
Contributor

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" ;)

Copy link
Member Author

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.
@laanwj
Copy link
Member Author

laanwj commented Feb 27, 2017

There you go, a one-liner now.

@JeremyRubin
Copy link
Contributor

utACK 19cafc6

@practicalswift
Copy link
Contributor

utACK 19cafc6

@sipa
Copy link
Member

sipa commented Feb 27, 2017

utACK

Copy link
Contributor

@gmaxwell gmaxwell left a comment

Choose a reason for hiding this comment

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

re-utACK.

@kallewoof
Copy link
Contributor

utACK 19cafc6

Copy link
Contributor

@jonasschnelli jonasschnelli left a comment

Choose a reason for hiding this comment

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

utACK 19cafc6

@laanwj laanwj merged commit 19cafc6 into bitcoin:master Feb 28, 2017
laanwj added a commit that referenced this pull request Feb 28, 2017
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
zkbot added a commit to zcash/zcash that referenced this pull request Apr 4, 2018
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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 5, 2019
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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 23, 2019
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
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 25, 2019
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
Krekeler added a commit to Krekeler/documentchain that referenced this pull request Jun 14, 2020
@str4d str4d mentioned this pull request Nov 9, 2020
zkbot added a commit to zcash/zcash that referenced this pull request Nov 10, 2020
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
random-zebra added a commit to PIVX-Project/PIVX that referenced this pull request Apr 23, 2021
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
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants