Make tinyformat noexcept: Use default error handling (assert(0 && reason)) on incorrect format strings #13391

pull practicalswift wants to merge 2 commits into bitcoin:master from practicalswift:non-throwing-tinyformat changing 2 files +1 −12
  1. practicalswift commented at 1:43 PM on June 4, 2018: contributor

    Make tinyformat noexcept: Use tinyformat's default error handling (assert(0 && reason);) instead of throwing tinyformat::format_error on incorrect format strings.

    The only place where tinyformat::format_error was handled was in LogPrintf(...) where it was handled to generate output which is equivalent to what assert(0 && reason); provides.

    Incorrect format strings are best handled explicitly locally in a "fail fast" manner. No need for propagation.

    Since tinyformat is used extensively via strprintf(…) large parts of the code base are switched from an implicit "might throw tinyformat::format_error" to "will not throw" from a compiler/static analyzer perspective with this change.

    Reducing the number of unnecessary exceptions thrown increases the signal-to-noise for humans when analyzing potential issues introduced by uncaught exceptions.

    These were the conditions that threw tinyformat::format_error prior to this commit:

    $ git grep TINYFORMAT_ERROR
    src/tinyformat.h:// Error handling: Define TINYFORMAT_ERROR to customize the error handling for
    src/tinyformat.h:#define TINYFORMAT_ERROR(reasonString) throw tinyformat::format_error(reasonString)
    src/tinyformat.h:#ifndef TINYFORMAT_ERROR
    src/tinyformat.h:#   define TINYFORMAT_ERROR(reason) assert(0 && reason)
    src/tinyformat.h:        TINYFORMAT_ERROR("tinyformat: Cannot convert from argument type to "
    src/tinyformat.h:        TINYFORMAT_ERROR("tinyformat: Not enough conversion specifiers in format string");
    src/tinyformat.h:            TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable width");
    src/tinyformat.h:                TINYFORMAT_ERROR("tinyformat: Not enough arguments to read variable precision");
    src/tinyformat.h:            TINYFORMAT_ERROR("tinyformat: the %a and %A conversion specs "
    src/tinyformat.h:            TINYFORMAT_ERROR("tinyformat: %n conversion spec not supported");
    src/tinyformat.h:            TINYFORMAT_ERROR("tinyformat: Conversion spec incorrectly "
    src/tinyformat.h:            TINYFORMAT_ERROR("tinyformat: Not enough format arguments");
    src/tinyformat.h:        TINYFORMAT_ERROR("tinyformat: Too many conversion specifiers in format string");
    
  2. Don't throw tinyformat::format_error on formatting errors. Fail locally instead. c1f453df88
  3. Simplify LogPrintf(...). tinyformat::format_error is no longer thrown. 7dc8fa8a9b
  4. fanquake added the label Utils/log/libs on Jun 4, 2018
  5. laanwj commented at 1:52 PM on June 4, 2018: member

    Tend towards NACK:

    • Changes to tinyformat.h should be made upstream.
    • A mistake in log message formatting should not crash the entire process. This was the case in the past, and resulted in near DoS vulnerabilities. The current state where a warning is logged instead is on purpose.

    This basically reverts b651270cd6bfdd6d7c4acf04d1a00c03bf09f03a (#9963) and I disagree with that strongly.

  6. practicalswift force-pushed on Jun 4, 2018
  7. practicalswift commented at 2:05 PM on June 4, 2018: contributor

    @laanwj Thanks for quick feedback. I've now reverted the tinyformat.h change to tinyformat code from upstream (the noexcept addition).

    Could you describe the issue that resulted in a near DoS vulnerability? As I read it #9963 was more about developer ergonomics? :-)

    Could a middle ground be to make strprintf(…) noexcept and keep LogPrintf(...) as is?

    None of the callers of strprintf(…) handle tinyformat::format_error from what I can see. Also, it is the strprintf(…) calls that create all the noise when I'm analyzing uncaught exceptions :-)

  8. laanwj commented at 2:18 PM on June 4, 2018: member

    Could you describe the issue that resulted in a near DoS vulnerability? As I read it #9963 was more about developer ergonomics? :-)

    I think we intentionally didn't mention the issue there. It's very simply: have an under-tested error path in the network code with an invalid LogPrintf() spec. Anything that triggers this will crash the process. A little loggable offense turns into a full DoS vector.

    Could a middle ground be to make strprintf(…) noexcept and keep LogPrintf(...) as is?

    I think that would be a better idea. If the output isn't just used for logging, it's a more serious error in any case.

  9. practicalswift commented at 2:20 PM on June 4, 2018: contributor

    @laanwj I see. Makes perfect sense. Closing!

  10. practicalswift closed this on Jun 4, 2018

  11. laanwj commented at 2:24 PM on June 4, 2018: member

    @practicalswift at least for the number of arguments versus number of specifiers, we could have a linter. Though it's harder to do than most of the checks.

  12. practicalswift commented at 2:39 PM on June 4, 2018: contributor

    @laanwj Good idea! I'll look into that when I'm done with my exception handling work :-)

  13. practicalswift deleted the branch on Apr 10, 2021
  14. DrahtBot locked this on Aug 18, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 15:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me