Merge bitcoin/bitcoin#31391: util: Drop boost posix_time in ParseISO8601DateTime

faf70cc994 Remove wallet::ParseISO8601DateTime, use ParseISO8601DateTime instead (MarcoFalke)
2222aecd5f util: Implement ParseISO8601DateTime based on C++20 (MarcoFalke)

Pull request description:

  `boost::posix_time` in `ParseISO8601DateTime` has many issues:

  * It parses random strings that are clearly invalid and returns a time value for them, see [1] below.
  * None of the separators `-`, or `:`, or `T`, or `Z` are validated.
  * It may crash when running under a hardened C++ library, see https://github.com/bitcoin/bitcoin/issues/28917.
  * It has been unmaintained for years, so reporting or fixing any issues will most likely be useless.
  * It pulls in a third-party dependency, when the functionality is already included in vanilla C++20.

  Fix all issues by replacing it with a simple helper function written in C++20.

  Fixes https://github.com/bitcoin/bitcoin/issues/28917.

  [1] The following patch passes on current master:

  ```diff
  diff --git a/src/wallet/test/rpc_util_tests.cpp b/src/wallet/test/rpc_util_tests.cpp
  index 32f6f5ab46..c1c94c7116 100644
  --- a/src/wallet/test/rpc_util_tests.cpp
  +++ b/src/wallet/test/rpc_util_tests.cpp
  @@ -12,6 +12,14 @@ BOOST_AUTO_TEST_SUITE(wallet_util_tests)

   BOOST_AUTO_TEST_CASE(util_ParseISO8601DateTime)
   {
  +    BOOST_CHECK_EQUAL(ParseISO8601DateTime("964296"), 242118028800);
  +    BOOST_CHECK_EQUAL(ParseISO8601DateTime("244622"), 15023836800);
  +    BOOST_CHECK_EQUAL(ParseISO8601DateTime("+INfINITy"), 9223372036854);
  +    BOOST_CHECK_EQUAL(ParseISO8601DateTime("7000802 01"), 158734166400);
  +    BOOST_CHECK_EQUAL(ParseISO8601DateTime("7469-2 +INfINITy"), 9223372036854);
  +    BOOST_CHECK_EQUAL(ParseISO8601DateTime("maXimum-datE-time"), 253402300799);
  +    BOOST_CHECK_EQUAL(ParseISO8601DateTime("577737     114maXimum-datE-time"), 253402300799);
  +
       BOOST_CHECK_EQUAL(ParseISO8601DateTime("1970-01-01T00:00:00Z"), 0);
       BOOST_CHECK_EQUAL(ParseISO8601DateTime("1960-01-01T00:00:00Z"), 0);
       BOOST_CHECK_EQUAL(ParseISO8601DateTime("2000-01-01T00:00:01Z"), 946684801);
  ```

ACKs for top commit:
  hebasto:
    ACK faf70cc994, I have reviewed the code and it looks OK.
  dergoegge:
    utACK faf70cc994

Tree-SHA512: 9dd745a356d04acf6200e13a6af52c51a9e2a0eeccea110093ce5da147b3c669c0eda918e46db0164c081a78c8feae3fe557a4759bea18449a8ff2d090095931
This commit is contained in:
merge-script
2024-12-04 11:21:43 +00:00
14 changed files with 94 additions and 69 deletions

View File

@@ -76,6 +76,7 @@ add_executable(fuzz
p2p_transport_serialization.cpp
package_eval.cpp
parse_hd_keypath.cpp
parse_iso8601.cpp
parse_numbers.cpp
parse_script.cpp
parse_univalue.cpp

View File

@@ -0,0 +1,27 @@
// Copyright (c) 2019-present The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h>
#include <util/time.h>
#include <cassert>
#include <cstdint>
#include <string>
#include <vector>
FUZZ_TARGET(parse_iso8601)
{
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
const int64_t random_time = fuzzed_data_provider.ConsumeIntegral<int32_t>();
const std::string random_string = fuzzed_data_provider.ConsumeRemainingBytesAsString();
const std::string iso8601_datetime = FormatISO8601DateTime(random_time);
(void)FormatISO8601Date(random_time);
const int64_t parsed_time_1{ParseISO8601DateTime(iso8601_datetime).value()};
assert(parsed_time_1 == random_time);
(void)ParseISO8601DateTime(random_string);
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2021-2022 The Bitcoin Core developers
// Copyright (c) 2021-present The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -34,8 +34,8 @@ CAmount ConsumeMoney(FuzzedDataProvider& fuzzed_data_provider, const std::option
int64_t ConsumeTime(FuzzedDataProvider& fuzzed_data_provider, const std::optional<int64_t>& min, const std::optional<int64_t>& max) noexcept
{
// Avoid t=0 (1970-01-01T00:00:00Z) since SetMockTime(0) disables mocktime.
static const int64_t time_min{946684801}; // 2000-01-01T00:00:01Z
static const int64_t time_max{4133980799}; // 2100-12-31T23:59:59Z
static const int64_t time_min{ParseISO8601DateTime("2000-01-01T00:00:01Z").value()};
static const int64_t time_max{ParseISO8601DateTime("2100-12-31T23:59:59Z").value()};
return fuzzed_data_provider.ConsumeIntegralInRange<int64_t>(min.value_or(time_min), max.value_or(time_max));
}