Skip to content

Commit 5e33620

Browse files
author
MarcoFalke
committed
Merge bitcoin/bitcoin#24371: util: Fix ReadBinaryFile reading beyond maxsize
a84650e util: Fix ReadBinaryFile reading beyond maxsize (klementtan) Pull request description: Currently `ReadBinaryFile` will read beyond `maxsize` if `maxsize` is not a multiple of `128` (size of buffer) This is due to `fread` being called with `count = 128` instead of `count = min(128, maxsize - retval.size()` at every iteration The following unit test will fail: ```cpp BOOST_AUTO_TEST_CASE(util_ReadWriteFile) { fs::path tmpfolder = m_args.GetDataDirBase(); fs::path tmpfile = tmpfolder / "read_binary.dat"; std::string expected_text(300,'c'); { std::ofstream file{tmpfile}; file << expected_text; } { // read half the contents in file auto [valid, text] = ReadBinaryFile(tmpfile, expected_text.size() / 2); BOOST_CHECK_EQUAL(text.size(), 150); } } ``` Error: ``` test/util_tests.cpp:2593: error: in "util_tests/util_ReadWriteFile": check text.size() == 150 has failed [256 != 150] ``` ACKs for top commit: laanwj: Code review ACK a84650e theStack: Code-review ACK a84650e Tree-SHA512: 752eebe58bc2102dec199b6775f8c3304d899f0ce36d6a022a58e27b076ba945ccd572858b19137b769effd8c6de73a9277f641be24dfb17657fb7173ea0eda0
2 parents 430acb7 + a84650e commit 5e33620

File tree

2 files changed

+50
-3
lines changed

2 files changed

+50
-3
lines changed

src/test/util_tests.cpp

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,18 @@
1717
#include <util/message.h> // For MessageSign(), MessageVerify(), MESSAGE_MAGIC
1818
#include <util/moneystr.h>
1919
#include <util/overflow.h>
20+
#include <util/readwritefile.h>
2021
#include <util/spanparsing.h>
2122
#include <util/strencodings.h>
2223
#include <util/string.h>
2324
#include <util/time.h>
2425
#include <util/vector.h>
2526

2627
#include <array>
27-
#include <optional>
28+
#include <fstream>
2829
#include <limits>
2930
#include <map>
31+
#include <optional>
3032
#include <stdint.h>
3133
#include <string.h>
3234
#include <thread>
@@ -2592,4 +2594,49 @@ BOOST_AUTO_TEST_CASE(util_ParseByteUnits)
25922594
BOOST_CHECK(!ParseByteUnits("1x", noop));
25932595
}
25942596

2597+
BOOST_AUTO_TEST_CASE(util_ReadBinaryFile)
2598+
{
2599+
fs::path tmpfolder = m_args.GetDataDirBase();
2600+
fs::path tmpfile = tmpfolder / "read_binary.dat";
2601+
std::string expected_text;
2602+
for (int i = 0; i < 30; i++) {
2603+
expected_text += "0123456789";
2604+
}
2605+
{
2606+
std::ofstream file{tmpfile};
2607+
file << expected_text;
2608+
}
2609+
{
2610+
// read all contents in file
2611+
auto [valid, text] = ReadBinaryFile(tmpfile);
2612+
BOOST_CHECK(valid);
2613+
BOOST_CHECK_EQUAL(text, expected_text);
2614+
}
2615+
{
2616+
// read half contents in file
2617+
auto [valid, text] = ReadBinaryFile(tmpfile, expected_text.size() / 2);
2618+
BOOST_CHECK(valid);
2619+
BOOST_CHECK_EQUAL(text, expected_text.substr(0, expected_text.size() / 2));
2620+
}
2621+
{
2622+
// read from non-existent file
2623+
fs::path invalid_file = tmpfolder / "invalid_binary.dat";
2624+
auto [valid, text] = ReadBinaryFile(invalid_file);
2625+
BOOST_CHECK(!valid);
2626+
BOOST_CHECK(text.empty());
2627+
}
2628+
}
2629+
2630+
BOOST_AUTO_TEST_CASE(util_WriteBinaryFile)
2631+
{
2632+
fs::path tmpfolder = m_args.GetDataDirBase();
2633+
fs::path tmpfile = tmpfolder / "write_binary.dat";
2634+
std::string expected_text = "bitcoin";
2635+
auto valid = WriteBinaryFile(tmpfile, expected_text);
2636+
std::string actual_text;
2637+
std::ifstream file{tmpfile};
2638+
file >> actual_text;
2639+
BOOST_CHECK(valid);
2640+
BOOST_CHECK_EQUAL(actual_text, expected_text);
2641+
}
25952642
BOOST_AUTO_TEST_SUITE_END()

src/util/readwritefile.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@ std::pair<bool,std::string> ReadBinaryFile(const fs::path &filename, size_t maxs
1818
std::string retval;
1919
char buffer[128];
2020
do {
21-
const size_t n = fread(buffer, 1, sizeof(buffer), f);
21+
const size_t n = fread(buffer, 1, std::min(sizeof(buffer), maxsize - retval.size()), f);
2222
// Check for reading errors so we don't return any data if we couldn't
2323
// read the entire file (or up to maxsize)
2424
if (ferror(f)) {
2525
fclose(f);
2626
return std::make_pair(false,"");
2727
}
2828
retval.append(buffer, buffer+n);
29-
} while (!feof(f) && retval.size() <= maxsize);
29+
} while (!feof(f) && retval.size() < maxsize);
3030
fclose(f);
3131
return std::make_pair(true,retval);
3232
}

0 commit comments

Comments
 (0)