util: Avoid potential uninitialized read in FormatISO8601DateTime(int64_t) by checking gmtime_s/gmtime_r return value#18162
Conversation
theStack
left a comment
There was a problem hiding this comment.
gmtime_s doesn't return a pointer, but errno_t (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/gmtime-s-gmtime32-s-gmtime64-s?view=vs-2019), hence the condition != 0 rather than == nullptr is needed in those cases to detect an error. See AppVeyor build failure.
5fe2368 to
6558ec3
Compare
|
@theStack Oh, thanks for notifying! :) Now addressed . Please re-review updated version :) |
|
The |
Weird: "The implementation of gmtime_s in Microsoft CRT is incompatible with the C standard since it has reversed parameter order." :) Luckily we use |
|
The unit tests are not passing: test/util_tests.cpp(155): error: in "util_tests/util_FormatParseISO8601DateTime": check FormatISO8601DateTime(std::numeric_limits<int64_t>::min()) == "" has failed [1970-01-01T00:00:00Z != ]
test/util_tests.cpp(156): error: in "util_tests/util_FormatParseISO8601DateTime": check FormatISO8601DateTime(std::numeric_limits<int64_t>::max()) == "" has failed [1969-12-31T23:59:59Z != ]
test/util_tests.cpp(157): error: in "util_tests/util_FormatParseISO8601DateTime": check FormatISO8601Date(std::numeric_limits<int64_t>::min()) == "" has failed [1970-01-01 != ]
test/util_tests.cpp(158): error: in "util_tests/util_FormatParseISO8601DateTime": check FormatISO8601Date(std::numeric_limits<int64_t>::max()) == "" has failed [1969-12-31 != ] |
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsNo conflicts as of last run. |
3025336 to
6558ec3
Compare
|
Added a valgrind CI job that would have caught this: see PR #18166 ( |
elichai
left a comment
There was a problem hiding this comment.
Nice find!
I'd refactor this out to a function that returns Optional<struct tm> but this can be done in a future PR
ACK 6558ec35654d1a9990dcb534b18b5c88c5a4e165
…) under valgrind to catch memory errors f2472f6 tests: Improve test runner output in case of target errors (practicalswift) 733bbec tests: Add --exclude integer,parse_iso8601 (temporarily) to make Travis pass until uninitialized read issue in FormatISO8601DateTime is fixed (practicalswift) 5ea8144 tests: Add support for excluding fuzz targets using -x/--exclude (practicalswift) 555236f tests: Remove -detect_leaks=0 from test/fuzz/test_runner.py - no longer needed (practicalswift) a3b539a ci: Run fuzz testing test cases under valgrind (practicalswift) Pull request description: Run fuzz testing [test cases (bitcoin-core/qa-assets)](https://github.com/bitcoin-core/qa-assets) under `valgrind`. This would have caught `util: Avoid potential uninitialized read in FormatISO8601DateTime(int64_t) by checking gmtime_s/gmtime_r return value` (#18162) and similar cases. ACKs for top commit: MarcoFalke: ACK f2472f6 👼 Tree-SHA512: bb0879d40167cf6906bc0ed31bed39db83c39c7beb46026f7b0ee53f28ff0526ad6fabc3f4cb3f5f18d3b8cafdcbf5f30105b35919f4e83697c71e838ed71493
…64_t nTime) by checking gmtime_s/gmtime_r return value
6558ec3 to
12a2f37
Compare
|
Rebased and removed |
…-assets) under valgrind to catch memory errors f2472f6 tests: Improve test runner output in case of target errors (practicalswift) 733bbec tests: Add --exclude integer,parse_iso8601 (temporarily) to make Travis pass until uninitialized read issue in FormatISO8601DateTime is fixed (practicalswift) 5ea8144 tests: Add support for excluding fuzz targets using -x/--exclude (practicalswift) 555236f tests: Remove -detect_leaks=0 from test/fuzz/test_runner.py - no longer needed (practicalswift) a3b539a ci: Run fuzz testing test cases under valgrind (practicalswift) Pull request description: Run fuzz testing [test cases (bitcoin-core/qa-assets)](https://github.com/bitcoin-core/qa-assets) under `valgrind`. This would have caught `util: Avoid potential uninitialized read in FormatISO8601DateTime(int64_t) by checking gmtime_s/gmtime_r return value` (bitcoin#18162) and similar cases. ACKs for top commit: MarcoFalke: ACK f2472f6 👼 Tree-SHA512: bb0879d40167cf6906bc0ed31bed39db83c39c7beb46026f7b0ee53f28ff0526ad6fabc3f4cb3f5f18d3b8cafdcbf5f30105b35919f4e83697c71e838ed71493
|
ACK 12a2f37 |
|
re-ACK 12a2f37 |
…atISO8601DateTime(int64_t) by checking gmtime_s/gmtime_r return value 12a2f37 util: Avoid potential uninitialized read in FormatISO8601DateTime(int64_t nTime) by checking gmtime_s/gmtime_r return value (practicalswift) Pull request description: Avoid potential uninitialized read in `FormatISO8601DateTime(int64_t)` by checking `gmtime_s`/`gmtime_r` return value. Before this patch `FormatISO8601DateTime(67768036191676800)` resulted in: ``` ==5930== Conditional jump or move depends on uninitialised value(s) ==5930== at 0x4F44C0A: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25) ==5930== by 0x4F511A4: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25) ==5930== by 0x4037C3: void tinyformat::formatValue<int>(std::ostream&, char const*, char const*, int, int const&) (tinyformat.h:358) ==5930== by 0x403725: void tinyformat::detail::FormatArg::formatImpl<int>(std::ostream&, char const*, char const*, int, void const*) (tinyformat.h:543) ==5930== by 0x402E02: tinyformat::detail::FormatArg::format(std::ostream&, char const*, char const*, int) const (tinyformat.h:528) ==5930== by 0x401B16: tinyformat::detail::formatImpl(std::ostream&, char const*, tinyformat::detail::FormatArg const*, int) (tinyformat.h:907) ==5930== by 0x4017AE: tinyformat::vformat(std::ostream&, char const*, tinyformat::FormatList const&) (tinyformat.h:1054) ==5930== by 0x401765: void tinyformat::format<int, int, int, int, int, int>(std::ostream&, char const*, int const&, int const&, int const&, int const&, int const&, int const&) (tinyformat.h:1064) ==5930== by 0x401656: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > tinyformat::format<int, int, int, int, int, int>(char const*, int const&, int const&, int const&, int const&, int const&, int const&) (tinyformat.h:1073) ==5930== by 0x4014CC: FormatISO8601DateTime[abi:cxx11](long) (…) ``` The same goes for other very large positive and negative arguments. Fix by simply checking the `gmtime_s`/`gmtime_r` return value :) ACKs for top commit: MarcoFalke: ACK 12a2f37 theStack: re-ACK bitcoin@12a2f37 elichai: re ACK 12a2f37 Tree-SHA512: 066142670d9bf0944d41fa3f3c702b1a460b5471b93e76a619b1e818ff9bb9c09fe14c4c37e9536a04c99533f7f21d1b08ac141e1b829ff87ee54c80d0e61d48
…t64_t) by checking gmtime_s/gmtime_r return value (bitcoin#18162)
…-assets) under valgrind to catch memory errors 3f686d1 ci: Run fuzz testing test cases (bitcoin-core/qa-assets) under valgrind to catch memory errors (practicalswift) Pull request description: Re-introduce the Travis valgrind fuzzing job which was removed by PR bitcoin#18899. The removal seems to have been made by accident since the removed job does not appear to be the source of the problem the PR set out to fix. --- Run fuzz testing [test cases (bitcoin-core/qa-assets)](https://github.com/bitcoin-core/qa-assets) under `valgrind`. This would have caught `util: Avoid potential uninitialized read in FormatISO8601DateTime(int64_t) by checking gmtime_s/gmtime_r return value` (bitcoin#18162) and similar cases. This fuzzing job was introduced in bitcoin#18166. Top commit has no ACKs. Tree-SHA512: 6e2681eb0ade6af465c5ea91ac163a337465d2130ec9880ba57a36d9af7c25682734586a32977dc25972d4f78483f339d680ea48c0ae13cf1dfa52b617aae401
…64_t nTime) by checking gmtime_s/gmtime_r return value Summary: ``` The same goes for other very large positive and negative arguments. Fix by simply checking the gmtime_s/gmtime_r return value :) ``` Backport of core [[bitcoin/bitcoin#18162 | PR18162]]. Test Plan: ninja all check-all Reviewers: #bitcoin_abc, PiRK Reviewed By: PiRK Differential Revision: https://reviews.bitcoinabc.org/D8219
…-assets) under valgrind to catch memory errors f2472f6 tests: Improve test runner output in case of target errors (practicalswift) 733bbec tests: Add --exclude integer,parse_iso8601 (temporarily) to make Travis pass until uninitialized read issue in FormatISO8601DateTime is fixed (practicalswift) 5ea8144 tests: Add support for excluding fuzz targets using -x/--exclude (practicalswift) 555236f tests: Remove -detect_leaks=0 from test/fuzz/test_runner.py - no longer needed (practicalswift) a3b539a ci: Run fuzz testing test cases under valgrind (practicalswift) Pull request description: Run fuzz testing [test cases (bitcoin-core/qa-assets)](https://github.com/bitcoin-core/qa-assets) under `valgrind`. This would have caught `util: Avoid potential uninitialized read in FormatISO8601DateTime(int64_t) by checking gmtime_s/gmtime_r return value` (bitcoin#18162) and similar cases. ACKs for top commit: MarcoFalke: ACK f2472f6 👼 Tree-SHA512: bb0879d40167cf6906bc0ed31bed39db83c39c7beb46026f7b0ee53f28ff0526ad6fabc3f4cb3f5f18d3b8cafdcbf5f30105b35919f4e83697c71e838ed71493
…atISO8601DateTime(int64_t) by checking gmtime_s/gmtime_r return value 12a2f37 util: Avoid potential uninitialized read in FormatISO8601DateTime(int64_t nTime) by checking gmtime_s/gmtime_r return value (practicalswift) Pull request description: Avoid potential uninitialized read in `FormatISO8601DateTime(int64_t)` by checking `gmtime_s`/`gmtime_r` return value. Before this patch `FormatISO8601DateTime(67768036191676800)` resulted in: ``` ==5930== Conditional jump or move depends on uninitialised value(s) ==5930== at 0x4F44C0A: std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25) ==5930== by 0x4F511A4: std::ostream& std::ostream::_M_insert<long>(long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25) ==5930== by 0x4037C3: void tinyformat::formatValue<int>(std::ostream&, char const*, char const*, int, int const&) (tinyformat.h:358) ==5930== by 0x403725: void tinyformat::detail::FormatArg::formatImpl<int>(std::ostream&, char const*, char const*, int, void const*) (tinyformat.h:543) ==5930== by 0x402E02: tinyformat::detail::FormatArg::format(std::ostream&, char const*, char const*, int) const (tinyformat.h:528) ==5930== by 0x401B16: tinyformat::detail::formatImpl(std::ostream&, char const*, tinyformat::detail::FormatArg const*, int) (tinyformat.h:907) ==5930== by 0x4017AE: tinyformat::vformat(std::ostream&, char const*, tinyformat::FormatList const&) (tinyformat.h:1054) ==5930== by 0x401765: void tinyformat::format<int, int, int, int, int, int>(std::ostream&, char const*, int const&, int const&, int const&, int const&, int const&, int const&) (tinyformat.h:1064) ==5930== by 0x401656: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > tinyformat::format<int, int, int, int, int, int>(char const*, int const&, int const&, int const&, int const&, int const&, int const&) (tinyformat.h:1073) ==5930== by 0x4014CC: FormatISO8601DateTime[abi:cxx11](long) (…) ``` The same goes for other very large positive and negative arguments. Fix by simply checking the `gmtime_s`/`gmtime_r` return value :) ACKs for top commit: MarcoFalke: ACK 12a2f37 theStack: re-ACK bitcoin@12a2f37 elichai: re ACK 12a2f37 Tree-SHA512: 066142670d9bf0944d41fa3f3c702b1a460b5471b93e76a619b1e818ff9bb9c09fe14c4c37e9536a04c99533f7f21d1b08ac141e1b829ff87ee54c80d0e61d48
f3f3d6c util: fix compilation with mingw-w64 7.0.0 (Fuzzbawls) f24da7d util: Avoid potential uninitialized read in FormatISO8601DateTime (Fuzzbawls) 120a12a util: Add type safe GetTime (Fuzzbawls) be48766 Fix for utiltime to compile with msvc. (Aaron Clauson) 2833406 Avoid std::locale/imbue in DateTimeStrFormat (Pieter Wuille) 3331c25 Format automatic wallet backup file names in ISO 8601 basic format (Fuzzbawls) c32a208 Format timestamps using ISO 8601 formatting (e.g. "2018-02-28T12:34:56Z") (practicalswift) f8bd173 [logging] log system time and mock time (John Newbery) Pull request description: This is a backport of a collection of upstream PRs to bring our time utility more up to date. The following upstream PRs are included: - bitcoin#10383 - bitcoin#12567 - bitcoin#12973 - bitcoin#13031 - bitcoin#16046 - bitcoin#18162 - bitcoin#18358 The two user-facing notable changes here have been documented in the release notes template. I've also connected the functionality that `-logtimemicros` was supposed to provide. ACKs for top commit: furszy: code review ACK f3f3d6c random-zebra: utACK f3f3d6c after rebase, and merging... Tree-SHA512: 64f9cc1f7fc65c192f3b3ab869c057a81e007cf0fae82ecd23993c6b51830e4bc80656c699ba40bb8e019115a24d1ea88a618be0c0d7112749d9ce125d62ce44
Avoid potential uninitialized read in
FormatISO8601DateTime(int64_t)by checkinggmtime_s/gmtime_rreturn value.Before this patch
FormatISO8601DateTime(67768036191676800)resulted in:The same goes for other very large positive and negative arguments.
Fix by simply checking the
gmtime_s/gmtime_rreturn value :)