Skip to content

Conversation

practicalswift
Copy link
Contributor

@practicalswift practicalswift commented Oct 21, 2019

Make all tests pass UBSan (-fsanitize=undefined) without using any UBSan suppressions.

From a fuzzing perspective it would be really nice to be able to run UBSan without having to deal with suppression files :)

Note that the commit c8c393b needs to be cherry-picked in from PR #17156 to get rid of the two alignment related suppressions :)

Before this PR:

$ ./configure --with-sanitizers=undefined
$ make
$ UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1" src/test/test_bitcoin
…
validation.cpp:2563:164: runtime error: division by zero
validation.cpp:2568:138: runtime error: division by zero
validation.cpp:2573:161: runtime error: division by zero
validation.cpp:2582:164: runtime error: division by zero
validation.cpp:2583:144: runtime error: division by zero
policy/fees.cpp:347:44: runtime error: division by zero
policy/fees.cpp:344:44: runtime error: division by zero
wallet/wallet.cpp:2049:67: runtime error: division by zero
wallet/wallet.cpp:3280:51: runtime error: division by zero
wallet/wallet.cpp:3283:51: runtime error: division by zero
…
$ echo $?
1
$ UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1" test/functional/test_runner.py
…
AssertionError: Unexpected stderr validation.cpp:2563:164: runtime error: division by zero
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior validation.cpp:2563:164 in
validation.cpp:2568:138: runtime error: division by zero
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior validation.cpp:2568:138 in
validation.cpp:2573:161: runtime error: division by zero
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior validation.cpp:2573:161 in
validation.cpp:2582:164: runtime error: division by zero
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior validation.cpp:2582:164 in
validation.cpp:2583:144: runtime error: division by zero
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior validation.cpp:2583:144 in !=
…
$ echo $?
1

After this PR (with cherry-pick as described above):

$ ./configure --with-sanitizers=undefined
$ make
$ UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1" src/test/test_bitcoin
$ echo $?
0
$ UBSAN_OPTIONS="print_stacktrace=1:halt_on_error=1" test/functional/test_runner.py
$ echo $?
0

Note: This PR is not a bug fix (there is no bug to fix!). We assume the floating-point types to fulfil the requirements of IEC 559 (IEEE 754) standard: floating-point division by zero is thus well-defined.

The IEC 559 (IEEE 754) assumption is made explicitly in assumptions.h and also checked at compile-time:

// Assumption: We assume the floating-point types to fulfill the requirements of
// IEC 559 (IEEE 754) standard.
// Example(s): Floating-point division by zero in ConnectBlock, CreateTransaction
// and EstimateMedianVal.
static_assert(std::numeric_limits<float>::is_iec559, "IEEE 754 float assumed");
static_assert(std::numeric_limits<double>::is_iec559, "IEEE 754 double assumed");

However, UBSan is not aware of that assumption we're making.

@DrahtBot
Copy link
Contributor

DrahtBot commented Oct 21, 2019

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

maflcko pushed a commit that referenced this pull request Oct 22, 2019
…es fixed). Add documentation.

0616138 tests: Remove no longer needed UBSan suppressions (issues fixed). Add documentation. (practicalswift)

Pull request description:

  Remove no longer needed UBSan suppressions (issues fixed). Add documentation.

  This PR is the CI-only subset of #17208 (which touches code).

  From a fuzzing perspective it would be really nice to be able to run UBSan with as few suppressions as possible :)

Top commit has no ACKs.

Tree-SHA512: a926ab3e80e12a805af110fbff470cdc61ef4db536919a5b8896ea8b70f761114a52d9b1c0f48b11c1d48338351bf2e003e01ce60c613612f26ba298dcc29cd9
@gmaxwell
Copy link
Contributor

Primary platforms Bitcoin runs on (x86 / win linux) are not strictly IEEE 754 (in particular, the standard x86 FPU is non-754 due to excess precision and non-strict truncation when moving between registers and memory). It's also not too uncommon for random obscure library code to silently dork around with rounding settings even on SSE (which is much more 754). Standard compiler optimization settings also break IEEE 754 handling even more than the base platform.

So I think it's not especially wise to make a very strong assumption of IEEE 754 overall.

I don't know if any of that directly impacts this change (though 0/0 is NaN as is 1 / +/-0) Also, there are values other than ==0.0 which in division can produce under/overflow so it's not instantly obvious that the 0.0 equality tests in the code are correct. (in general, equality tests in floating point code are frequent sources of bugs).

Inserting extra floating point variables to silence a non-error error seems kinda ugly. Considering that these are just debugging messages, it might be better to just rework them (e.g. don't print if there is nothing to report, or don't divide numbers just give the raw numbers). Returning "inf" in debug lines also might needlessly mess up parsing just as much as not outputting the log in 'impossible' cases where the time elapsed is zero.

@practicalswift
Copy link
Contributor Author

@gmaxwell Thanks for reviewing. Those are all good points. I agree that we should be careful with the IEEE 754 assumptions we're making.

I've now pushed an updated version of this PR -- now doing:

1.)

-static int64_t nBlocksTotal = 0;
+static int64_t nBlocksTotal = 1;

As suggested in a related PR: "This change would have been better done-- easier to review for correctness, more stable against "regression"-- by simply changing the existing initialization constant for nBlocksTotal from 0 to 1."

2.)

As suggested: now giving raw numbers instead of percentages.

3.)

Setting m_scanning_progress to 0.0 in the case of !(progress_end - progress_begin > 0.0) to avoid any potential floating-point division by zero.

Please re-review :)


Fun bonus trivia
$ cling
[cling]$ #include <iostream>
[cling]$ void f(double d) {
[cling]$     if (d == 0.0) {
[cling]$     } else if (d < 0.0) {
[cling]$     } else if (d > 0.0) {
[cling]$     } else {
[cling]$         std::cout << "reachable.\n";
[cling]$     }
[cling]$ }
[cling]$ f(0.0/0.0)
reachable.
[cling]$ .q
$

:)

@practicalswift practicalswift force-pushed the ubsan-warnings branch 2 times, most recently from c4107b2 to ed3e044 Compare October 29, 2019 23:41
@practicalswift
Copy link
Contributor Author

@MarcoFalke @laanwj @Empact @promag You've all shown interest in the sanitizers before: would you mind reviewing? :)

@practicalswift
Copy link
Contributor Author

Feel free to review the updated version - would be nice to get rid of the UBSan suppressions :)

Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

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

Big concept ACK -- I was about to open a PR about this and then saw this PR.

Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

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

ACK 9724a0c code review, built with sanitizers=undefined and -Weverything, ran tests/bitcoind.

I'm sympathetic to @Empact's comments and suggestions above (and mine).

I'd like to see this PR and #17708 merged to facilitate and encourage testing with UBSan by default as a general review practice.

@practicalswift
Copy link
Contributor Author

@jonatack I'm leaving this one as up for grabs. Feel free to cherry pick in the commits in a new PR: I think this PR has a greater probability of getting merged if you submit it TBH :)

@jonatack
Copy link
Member

@practicalswift heh, to the contrary you are more effective than I at having testing improvements merged -- nevertheless, I empathise :) Let's see if #15283 makes headway.

@practicalswift
Copy link
Contributor Author

practicalswift commented Feb 23, 2020

I was informed that there was some interest expressed in this PR at this week's meeting. Re-opening to give it another chance :)

Pinging in @jonatack, @laanwj. @instagibbs and @elichai who I understood sounded positive at the meeting - would you mind reviewing? :)

This net change of -8 lines should hopefully be easy to review for correctness :)

@elichai
Copy link
Contributor

elichai commented Feb 23, 2020

I can't get the sanitizer to complain about these, tried both gcc and clang with commit ab9de43

$ make clean
$ ./configure --with-sanitizers=undefined --with-incompatible-bdb
$ make
$ ./src/test/test_bitcoin
Running 396 test cases...

*** No errors detected

tried even removing the first 6 lines in ./test/sanitizer/suppressions/ubsan
@practicalswift what am I doing wrong?

@jonatack
Copy link
Member

@elichai try make distclean?

@jonatack
Copy link
Member

@practicalswift thanks for re-opening. I prefer this PR for the reasons I mention in #15283 (comment), so my review above stands.

@elichai
Copy link
Contributor

elichai commented Feb 23, 2020

@elichai try make distclean?

Still nothing :/
Maybe I should re-clone? or can it be because I have a very new compiler? (GCC 9.2.1 and Clang 9.0.1)

It does seem to be part of the build: (and I added a out of bound read to one of the tests and it caught it)

Options used to compile and link:                                                                                                                                                                                                                                               
  with wallet   = yes                                                                                                                   
  with gui / qt = yes                                      
    with qr     = yes                                                                                                                   
  with zmq      = yes                                                                                                                   
  with test     = yes                                                                                                                   
    with prop   = no                                                                                                                    
    with fuzz   = no                                
  with bench    = yes                           
  with upnp     = yes                            
  use asm       = yes                                          
  sanitizers    = undefined                                                                                                             
  debug enabled = no                                                                                                                                                                                                                                                            
  gprof enabled = no                                                                                                                    
  werror        = no                                                                                                                    
                                                                                                                                        
  target os     = linux                                    
  build os      =                                                                                                                                                                                                                                                               

  CC            = /usr/bin/ccache gcc
  CFLAGS        = -g -O2
  CPPFLAGS      =   -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2  -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS
  CXX           = /usr/bin/ccache g++ -std=c++11
  CXXFLAGS      =   -fstack-reuse=none -Wstack-protector -fstack-protector-all  -Wall -Wextra -Wformat -Wvla -Wswitch -Wredundant-decls -Wunused-variable -Wdate-time  -Wno-unused-parameter -Wno-implicit-fallthrough   -g -O2
  LDFLAGS       = -pthread  -Wl,-z,relro -Wl,-z,now -pie  
  ARFLAGS       = cr

@practicalswift
Copy link
Contributor Author

@elichai I think the reason you're not seeing this when using Clang is that you're using a more recent Clang than the one we're using in Travis: float-divide-by-zero was removed from the -fsanitize=undefined by https://reviews.llvm.org/D63793. Could that be the case?

@elichai
Copy link
Contributor

elichai commented Feb 24, 2020

@elichai I think the reason you're not seeing this when using Clang is that you're using a more recent Clang than the one we're using in Travis: float-divide-by-zero was removed from the -fsanitize=undefined by https://reviews.llvm.org/D63793. Could that be the case?

Makes sense. but I also can't see it with gcc not just clang
Just found this:
https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html

-fsanitize=float-divide-by-zero
Detect floating-point division by zero. Unlike other similar options, -fsanitize=float-divide-by-zero is not enabled by -fsanitize=undefined, since floating-point division by zero can be a legitimate way of obtaining infinities and NaNs.

@elichai
Copy link
Contributor

elichai commented Feb 24, 2020

Finally.
Before:

./configure --with-sanitizers=undefined,float-divide-by-zero --with-incompatible-bdb
make
./src/test/test_bitcoin                          
Running 396 test cases...                                                                                
 ==                                                                                                      
wallet/wallet.cpp:1669:67: runtime error: division by zero                                               
wallet/wallet.cpp:2945:51: runtime error: division by zero                                                                                                                                                         
wallet/wallet.cpp:2942:51: runtime error: division by zero                                               
                                                                                                         
*** No errors detected                                                                                   

After:

./configure --with-sanitizers=undefined,float-divide-by-zero --with-incompatible-bdb
make
./src/test/test_bitcoin                          
Running 396 test cases...

*** No errors detected

@practicalswift
Copy link
Contributor Author

I'll leave this PR open for one week to allow for ACK:s to measure interest :)

Will close if no interest shown :)

@practicalswift
Copy link
Contributor Author

Closing due to lack of interest :)

@practicalswift practicalswift deleted the ubsan-warnings branch April 10, 2021 19:39
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Sep 11, 2021
…s (issues fixed). Add documentation.

0616138 tests: Remove no longer needed UBSan suppressions (issues fixed). Add documentation. (practicalswift)

Pull request description:

  Remove no longer needed UBSan suppressions (issues fixed). Add documentation.

  This PR is the CI-only subset of bitcoin#17208 (which touches code).

  From a fuzzing perspective it would be really nice to be able to run UBSan with as few suppressions as possible :)

Top commit has no ACKs.

Tree-SHA512: a926ab3e80e12a805af110fbff470cdc61ef4db536919a5b8896ea8b70f761114a52d9b1c0f48b11c1d48338351bf2e003e01ce60c613612f26ba298dcc29cd9
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Sep 11, 2021
…s (issues fixed). Add documentation.

0616138 tests: Remove no longer needed UBSan suppressions (issues fixed). Add documentation. (practicalswift)

Pull request description:

  Remove no longer needed UBSan suppressions (issues fixed). Add documentation.

  This PR is the CI-only subset of bitcoin#17208 (which touches code).

  From a fuzzing perspective it would be really nice to be able to run UBSan with as few suppressions as possible :)

Top commit has no ACKs.

Tree-SHA512: a926ab3e80e12a805af110fbff470cdc61ef4db536919a5b8896ea8b70f761114a52d9b1c0f48b11c1d48338351bf2e003e01ce60c613612f26ba298dcc29cd9
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Sep 12, 2021
…s (issues fixed). Add documentation.

0616138 tests: Remove no longer needed UBSan suppressions (issues fixed). Add documentation. (practicalswift)

Pull request description:

  Remove no longer needed UBSan suppressions (issues fixed). Add documentation.

  This PR is the CI-only subset of bitcoin#17208 (which touches code).

  From a fuzzing perspective it would be really nice to be able to run UBSan with as few suppressions as possible :)

Top commit has no ACKs.

Tree-SHA512: a926ab3e80e12a805af110fbff470cdc61ef4db536919a5b8896ea8b70f761114a52d9b1c0f48b11c1d48338351bf2e003e01ce60c613612f26ba298dcc29cd9
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Sep 12, 2021
…s (issues fixed). Add documentation.

0616138 tests: Remove no longer needed UBSan suppressions (issues fixed). Add documentation. (practicalswift)

Pull request description:

  Remove no longer needed UBSan suppressions (issues fixed). Add documentation.

  This PR is the CI-only subset of bitcoin#17208 (which touches code).

  From a fuzzing perspective it would be really nice to be able to run UBSan with as few suppressions as possible :)

Top commit has no ACKs.

Tree-SHA512: a926ab3e80e12a805af110fbff470cdc61ef4db536919a5b8896ea8b70f761114a52d9b1c0f48b11c1d48338351bf2e003e01ce60c613612f26ba298dcc29cd9
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Sep 12, 2021
…s (issues fixed). Add documentation.

0616138 tests: Remove no longer needed UBSan suppressions (issues fixed). Add documentation. (practicalswift)

Pull request description:

  Remove no longer needed UBSan suppressions (issues fixed). Add documentation.

  This PR is the CI-only subset of bitcoin#17208 (which touches code).

  From a fuzzing perspective it would be really nice to be able to run UBSan with as few suppressions as possible :)

Top commit has no ACKs.

Tree-SHA512: a926ab3e80e12a805af110fbff470cdc61ef4db536919a5b8896ea8b70f761114a52d9b1c0f48b11c1d48338351bf2e003e01ce60c613612f26ba298dcc29cd9
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Sep 14, 2021
…s (issues fixed). Add documentation.

0616138 tests: Remove no longer needed UBSan suppressions (issues fixed). Add documentation. (practicalswift)

Pull request description:

  Remove no longer needed UBSan suppressions (issues fixed). Add documentation.

  This PR is the CI-only subset of bitcoin#17208 (which touches code).

  From a fuzzing perspective it would be really nice to be able to run UBSan with as few suppressions as possible :)

Top commit has no ACKs.

Tree-SHA512: a926ab3e80e12a805af110fbff470cdc61ef4db536919a5b8896ea8b70f761114a52d9b1c0f48b11c1d48338351bf2e003e01ce60c613612f26ba298dcc29cd9
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Sep 14, 2021
…s (issues fixed). Add documentation.

0616138 tests: Remove no longer needed UBSan suppressions (issues fixed). Add documentation. (practicalswift)

Pull request description:

  Remove no longer needed UBSan suppressions (issues fixed). Add documentation.

  This PR is the CI-only subset of bitcoin#17208 (which touches code).

  From a fuzzing perspective it would be really nice to be able to run UBSan with as few suppressions as possible :)

Top commit has no ACKs.

Tree-SHA512: a926ab3e80e12a805af110fbff470cdc61ef4db536919a5b8896ea8b70f761114a52d9b1c0f48b11c1d48338351bf2e003e01ce60c613612f26ba298dcc29cd9
Munkybooty pushed a commit to Munkybooty/dash that referenced this pull request Apr 29, 2022
…s (issues fixed). Add documentation.

0616138 tests: Remove no longer needed UBSan suppressions (issues fixed). Add documentation. (practicalswift)

Pull request description:

  Remove no longer needed UBSan suppressions (issues fixed). Add documentation.

  This PR is the CI-only subset of bitcoin#17208 (which touches code).

  From a fuzzing perspective it would be really nice to be able to run UBSan with as few suppressions as possible :)

Top commit has no ACKs.

Tree-SHA512: a926ab3e80e12a805af110fbff470cdc61ef4db536919a5b8896ea8b70f761114a52d9b1c0f48b11c1d48338351bf2e003e01ce60c613612f26ba298dcc29cd9
Munkybooty pushed a commit to Munkybooty/dash that referenced this pull request May 12, 2022
…s (issues fixed). Add documentation.

0616138 tests: Remove no longer needed UBSan suppressions (issues fixed). Add documentation. (practicalswift)

Pull request description:

  Remove no longer needed UBSan suppressions (issues fixed). Add documentation.

  This PR is the CI-only subset of bitcoin#17208 (which touches code).

  From a fuzzing perspective it would be really nice to be able to run UBSan with as few suppressions as possible :)

Top commit has no ACKs.

Tree-SHA512: a926ab3e80e12a805af110fbff470cdc61ef4db536919a5b8896ea8b70f761114a52d9b1c0f48b11c1d48338351bf2e003e01ce60c613612f26ba298dcc29cd9
Munkybooty pushed a commit to Munkybooty/dash that referenced this pull request May 12, 2022
…s (issues fixed). Add documentation.

0616138 tests: Remove no longer needed UBSan suppressions (issues fixed). Add documentation. (practicalswift)

Pull request description:

  Remove no longer needed UBSan suppressions (issues fixed). Add documentation.

  This PR is the CI-only subset of bitcoin#17208 (which touches code).

  From a fuzzing perspective it would be really nice to be able to run UBSan with as few suppressions as possible :)

Top commit has no ACKs.

Tree-SHA512: a926ab3e80e12a805af110fbff470cdc61ef4db536919a5b8896ea8b70f761114a52d9b1c0f48b11c1d48338351bf2e003e01ce60c613612f26ba298dcc29cd9
Munkybooty pushed a commit to Munkybooty/dash that referenced this pull request May 17, 2022
…s (issues fixed). Add documentation.

0616138 tests: Remove no longer needed UBSan suppressions (issues fixed). Add documentation. (practicalswift)

Pull request description:

  Remove no longer needed UBSan suppressions (issues fixed). Add documentation.

  This PR is the CI-only subset of bitcoin#17208 (which touches code).

  From a fuzzing perspective it would be really nice to be able to run UBSan with as few suppressions as possible :)

Top commit has no ACKs.

Tree-SHA512: a926ab3e80e12a805af110fbff470cdc61ef4db536919a5b8896ea8b70f761114a52d9b1c0f48b11c1d48338351bf2e003e01ce60c613612f26ba298dcc29cd9
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 18, 2022
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.

8 participants