mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 10:43:19 -03:00
Merge bitcoin/bitcoin#24371: util: Fix ReadBinaryFile
reading beyond maxsize
a84650ebd5
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 ACKa84650ebd5
theStack: Code-review ACKa84650ebd5
Tree-SHA512: 752eebe58bc2102dec199b6775f8c3304d899f0ce36d6a022a58e27b076ba945ccd572858b19137b769effd8c6de73a9277f641be24dfb17657fb7173ea0eda0
This commit is contained in:
commit
5e33620ad8
2 changed files with 50 additions and 3 deletions
|
@ -17,6 +17,7 @@
|
|||
#include <util/message.h> // For MessageSign(), MessageVerify(), MESSAGE_MAGIC
|
||||
#include <util/moneystr.h>
|
||||
#include <util/overflow.h>
|
||||
#include <util/readwritefile.h>
|
||||
#include <util/spanparsing.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <util/string.h>
|
||||
|
@ -24,9 +25,10 @@
|
|||
#include <util/vector.h>
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <thread>
|
||||
|
@ -2592,4 +2594,49 @@ BOOST_AUTO_TEST_CASE(util_ParseByteUnits)
|
|||
BOOST_CHECK(!ParseByteUnits("1x", noop));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(util_ReadBinaryFile)
|
||||
{
|
||||
fs::path tmpfolder = m_args.GetDataDirBase();
|
||||
fs::path tmpfile = tmpfolder / "read_binary.dat";
|
||||
std::string expected_text;
|
||||
for (int i = 0; i < 30; i++) {
|
||||
expected_text += "0123456789";
|
||||
}
|
||||
{
|
||||
std::ofstream file{tmpfile};
|
||||
file << expected_text;
|
||||
}
|
||||
{
|
||||
// read all contents in file
|
||||
auto [valid, text] = ReadBinaryFile(tmpfile);
|
||||
BOOST_CHECK(valid);
|
||||
BOOST_CHECK_EQUAL(text, expected_text);
|
||||
}
|
||||
{
|
||||
// read half contents in file
|
||||
auto [valid, text] = ReadBinaryFile(tmpfile, expected_text.size() / 2);
|
||||
BOOST_CHECK(valid);
|
||||
BOOST_CHECK_EQUAL(text, expected_text.substr(0, expected_text.size() / 2));
|
||||
}
|
||||
{
|
||||
// read from non-existent file
|
||||
fs::path invalid_file = tmpfolder / "invalid_binary.dat";
|
||||
auto [valid, text] = ReadBinaryFile(invalid_file);
|
||||
BOOST_CHECK(!valid);
|
||||
BOOST_CHECK(text.empty());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(util_WriteBinaryFile)
|
||||
{
|
||||
fs::path tmpfolder = m_args.GetDataDirBase();
|
||||
fs::path tmpfile = tmpfolder / "write_binary.dat";
|
||||
std::string expected_text = "bitcoin";
|
||||
auto valid = WriteBinaryFile(tmpfile, expected_text);
|
||||
std::string actual_text;
|
||||
std::ifstream file{tmpfile};
|
||||
file >> actual_text;
|
||||
BOOST_CHECK(valid);
|
||||
BOOST_CHECK_EQUAL(actual_text, expected_text);
|
||||
}
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
|
@ -18,7 +18,7 @@ std::pair<bool,std::string> ReadBinaryFile(const fs::path &filename, size_t maxs
|
|||
std::string retval;
|
||||
char buffer[128];
|
||||
do {
|
||||
const size_t n = fread(buffer, 1, sizeof(buffer), f);
|
||||
const size_t n = fread(buffer, 1, std::min(sizeof(buffer), maxsize - retval.size()), f);
|
||||
// Check for reading errors so we don't return any data if we couldn't
|
||||
// read the entire file (or up to maxsize)
|
||||
if (ferror(f)) {
|
||||
|
@ -26,7 +26,7 @@ std::pair<bool,std::string> ReadBinaryFile(const fs::path &filename, size_t maxs
|
|||
return std::make_pair(false,"");
|
||||
}
|
||||
retval.append(buffer, buffer+n);
|
||||
} while (!feof(f) && retval.size() <= maxsize);
|
||||
} while (!feof(f) && retval.size() < maxsize);
|
||||
fclose(f);
|
||||
return std::make_pair(true,retval);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue