Skip to content

Commit 018d80a

Browse files
Merge dashpay#6398: backport: 24306, 24312, 24371
ba7e500 refactor: more of 24306 (GetPathArg in Dash-specific code) (UdjinM6) 562e3f7 Merge bitcoin#24371: util: Fix ReadBinaryFile reading beyond maxsize (MarcoFalke) 3383b79 Merge bitcoin#24312: addrman: Log too low compat value (MarcoFalke) d96983a Merge bitcoin#24306: util: Make ArgsManager::GetPathArg more widely usable (MarcoFalke) Pull request description: ## Issue being fixed or feature implemented A few simple backports ## What was done? ## How Has This Been Tested? Built locally; see CI ## Breaking Changes None ## Checklist: _Go over all the following points, and put an `x` in all the boxes that apply._ - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK ba7e500 kwvg: utACK ba7e500 Tree-SHA512: 42f41cb04945af15bfa4581ae53354eec88d4cdec44ab7c0100edcfe2fa71a95e05073e76b8d3935bd05cd5ee1f5cd5b34d2ed99e7eb551475abdc77f1ffff7c
2 parents cde4d02 + ba7e500 commit 018d80a

File tree

12 files changed

+113
-29
lines changed

12 files changed

+113
-29
lines changed

src/addrman.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,12 +244,18 @@ void AddrManImpl::Unserialize(Stream& s_)
244244

245245
uint8_t compat;
246246
s >> compat;
247+
if (compat < INCOMPATIBILITY_BASE) {
248+
throw std::ios_base::failure(strprintf(
249+
"Corrupted addrman database: The compat value (%u) "
250+
"is lower than the expected minimum value %u.",
251+
compat, INCOMPATIBILITY_BASE));
252+
}
247253
const uint8_t lowest_compatible = compat - INCOMPATIBILITY_BASE;
248254
if (lowest_compatible > FILE_FORMAT) {
249255
throw InvalidAddrManVersionError(strprintf(
250256
"Unsupported format of addrman database: %u. It is compatible with formats >=%u, "
251257
"but the maximum supported by this version of %s is %u.",
252-
uint8_t{format}, uint8_t{lowest_compatible}, PACKAGE_NAME, uint8_t{FILE_FORMAT}));
258+
uint8_t{format}, lowest_compatible, PACKAGE_NAME, uint8_t{FILE_FORMAT}));
253259
}
254260

255261
s >> nKey;

src/bench/bench_bitcoin.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ int main(int argc, char** argv)
111111
args.asymptote = parseAsymptote(argsman.GetArg("-asymptote", ""));
112112
args.is_list_only = argsman.GetBoolArg("-list", false);
113113
args.min_time = std::chrono::milliseconds(argsman.GetArg("-min_time", DEFAULT_MIN_TIME_MS));
114-
args.output_csv = fs::PathFromString(argsman.GetArg("-output_csv", ""));
115-
args.output_json = fs::PathFromString(argsman.GetArg("-output_json", ""));
114+
args.output_csv = argsman.GetPathArg("-output_csv");
115+
args.output_json = argsman.GetPathArg("-output_json");
116116
args.regex_filter = argsman.GetArg("-filter", DEFAULT_BENCH_FILTER);
117117

118118
benchmark::BenchRunner::RunAll(args);

src/init.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ static const char* BITCOIN_PID_FILENAME = "dashd.pid";
160160

161161
static fs::path GetPidFile(const ArgsManager& args)
162162
{
163-
return AbsPathForConfigVal(fs::PathFromString(args.GetArg("-pid", BITCOIN_PID_FILENAME)));
163+
return AbsPathForConfigVal(args.GetPathArg("-pid", BITCOIN_PID_FILENAME));
164164
}
165165

166166
[[nodiscard]] static bool CreatePidFile(const ArgsManager& args)
@@ -1566,10 +1566,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
15661566
// Read asmap file if configured
15671567
std::vector<bool> asmap;
15681568
if (args.IsArgSet("-asmap")) {
1569-
fs::path asmap_path = fs::PathFromString(args.GetArg("-asmap", ""));
1570-
if (asmap_path.empty()) {
1571-
asmap_path = fs::PathFromString(DEFAULT_ASMAP_FILENAME);
1572-
}
1569+
fs::path asmap_path = args.GetPathArg("-asmap", DEFAULT_ASMAP_FILENAME);
15731570
if (!asmap_path.is_absolute()) {
15741571
asmap_path = gArgs.GetDataDirNet() / asmap_path;
15751572
}

src/init/common.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void AddLoggingArgs(ArgsManager& argsman)
7777
void SetLoggingOptions(const ArgsManager& args)
7878
{
7979
LogInstance().m_print_to_file = !args.IsArgNegated("-debuglogfile");
80-
LogInstance().m_file_path = AbsPathForConfigVal(fs::PathFromString(args.GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE)));
80+
LogInstance().m_file_path = AbsPathForConfigVal(args.GetPathArg("-debuglogfile", DEFAULT_DEBUGLOGFILE));
8181
LogInstance().m_print_to_console = args.GetBoolArg("-printtoconsole", !args.GetBoolArg("-daemon", false));
8282
LogInstance().m_log_timestamps = args.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
8383
LogInstance().m_log_time_micros = args.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);

src/qt/bitcoin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ int GuiMain(int argc, char* argv[])
680680
}
681681
// Validate/set custom css directory
682682
if (gArgs.IsArgSet("-custom-css-dir")) {
683-
fs::path customDir = fs::PathFromString(gArgs.GetArg("-custom-css-dir", ""));
683+
fs::path customDir = gArgs.GetPathArg("-custom-css-dir");
684684
QString strCustomDir = GUIUtil::PathToQString(customDir);
685685
std::vector<QString> vecRequiredFiles = GUIUtil::listStyleSheets();
686686
QString strFile;

src/test/getarg_tests.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,24 @@ BOOST_AUTO_TEST_CASE(patharg)
243243

244244
ResetArgs("-dir=user/.bitcoin/.//");
245245
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir"), relative_path);
246+
247+
// Check negated and default argument handling. Specifying an empty argument
248+
// is the same as not specifying the argument. This is convenient for
249+
// scripting so later command line arguments can override earlier command
250+
// line arguments or bitcoin.conf values. Currently the -dir= case cannot be
251+
// distinguished from -dir case with no assignment, but #16545 would add the
252+
// ability to distinguish these in the future (and treat the no-assign case
253+
// like an imperative command or an error).
254+
ResetArgs("");
255+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir", "default"), fs::path{"default"});
256+
ResetArgs("-dir=override");
257+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir", "default"), fs::path{"override"});
258+
ResetArgs("-dir=");
259+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir", "default"), fs::path{"default"});
260+
ResetArgs("-dir");
261+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir", "default"), fs::path{"default"});
262+
ResetArgs("-nodir");
263+
BOOST_CHECK_EQUAL(m_local_args.GetPathArg("-dir", "default"), fs::path{""});
246264
}
247265

248266
BOOST_AUTO_TEST_CASE(doubledash)

src/test/util_tests.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
#include <util/moneystr.h>
1919
#include <util/overflow.h>
2020
#include <util/ranges_set.h>
21+
#include <util/readwritefile.h>
2122
#include <util/spanparsing.h>
2223
#include <util/strencodings.h>
2324
#include <util/string.h>
2425
#include <util/time.h>
2526
#include <util/vector.h>
2627

2728
#include <array>
29+
#include <fstream>
2830
#include <deque>
2931
#include <optional>
3032
#include <random>
@@ -2747,6 +2749,52 @@ BOOST_AUTO_TEST_CASE(util_ParseByteUnits)
27472749
BOOST_CHECK(!ParseByteUnits("1x", noop));
27482750
}
27492751

2752+
BOOST_AUTO_TEST_CASE(util_ReadBinaryFile)
2753+
{
2754+
fs::path tmpfolder = m_args.GetDataDirBase();
2755+
fs::path tmpfile = tmpfolder / "read_binary.dat";
2756+
std::string expected_text;
2757+
for (int i = 0; i < 30; i++) {
2758+
expected_text += "0123456789";
2759+
}
2760+
{
2761+
std::ofstream file{tmpfile};
2762+
file << expected_text;
2763+
}
2764+
{
2765+
// read all contents in file
2766+
auto [valid, text] = ReadBinaryFile(tmpfile);
2767+
BOOST_CHECK(valid);
2768+
BOOST_CHECK_EQUAL(text, expected_text);
2769+
}
2770+
{
2771+
// read half contents in file
2772+
auto [valid, text] = ReadBinaryFile(tmpfile, expected_text.size() / 2);
2773+
BOOST_CHECK(valid);
2774+
BOOST_CHECK_EQUAL(text, expected_text.substr(0, expected_text.size() / 2));
2775+
}
2776+
{
2777+
// read from non-existent file
2778+
fs::path invalid_file = tmpfolder / "invalid_binary.dat";
2779+
auto [valid, text] = ReadBinaryFile(invalid_file);
2780+
BOOST_CHECK(!valid);
2781+
BOOST_CHECK(text.empty());
2782+
}
2783+
}
2784+
2785+
BOOST_AUTO_TEST_CASE(util_WriteBinaryFile)
2786+
{
2787+
fs::path tmpfolder = m_args.GetDataDirBase();
2788+
fs::path tmpfile = tmpfolder / "write_binary.dat";
2789+
std::string expected_text = "bitcoin";
2790+
auto valid = WriteBinaryFile(tmpfile, expected_text);
2791+
std::string actual_text;
2792+
std::ifstream file{tmpfile};
2793+
file >> actual_text;
2794+
BOOST_CHECK(valid);
2795+
BOOST_CHECK_EQUAL(actual_text, expected_text);
2796+
}
2797+
27502798
BOOST_AUTO_TEST_CASE(clearshrink_test)
27512799
{
27522800
{

src/util/readwritefile.cpp

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

src/util/system.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,12 @@ std::optional<unsigned int> ArgsManager::GetArgFlags(const std::string& name) co
407407
return std::nullopt;
408408
}
409409

410-
fs::path ArgsManager::GetPathArg(std::string pathlike_arg) const
410+
fs::path ArgsManager::GetPathArg(std::string arg, const fs::path& default_value) const
411411
{
412-
auto result = fs::PathFromString(GetArg(pathlike_arg, "")).lexically_normal();
412+
if (IsArgNegated(arg)) return fs::path{};
413+
std::string path_str = GetArg(arg, "");
414+
if (path_str.empty()) return default_value;
415+
fs::path result = fs::PathFromString(path_str).lexically_normal();
413416
// Remove trailing slash, if present.
414417
return result.has_filename() ? result : result.parent_path();
415418
}
@@ -478,7 +481,7 @@ fs::path ArgsManager::GetBackupsDirPath()
478481
if (!IsArgSet("-walletbackupsdir"))
479482
return GetDataDirNet() / "backups";
480483

481-
return fs::absolute(fs::PathFromString(GetArg("-walletbackupsdir", "")));
484+
return fs::absolute(GetPathArg("-walletbackupsdir"));
482485
}
483486

484487
void ArgsManager::ClearPathCache()
@@ -544,12 +547,12 @@ bool ArgsManager::InitSettings(std::string& error)
544547

545548
bool ArgsManager::GetSettingsPath(fs::path* filepath, bool temp) const
546549
{
547-
if (IsArgNegated("-settings")) {
550+
fs::path settings = GetPathArg("-settings", fs::path{BITCOIN_SETTINGS_FILENAME});
551+
if (settings.empty()) {
548552
return false;
549553
}
550554
if (filepath) {
551-
std::string settings = GetArg("-settings", BITCOIN_SETTINGS_FILENAME);
552-
*filepath = fsbridge::AbsPathJoin(GetDataDirNet(), fs::PathFromString(temp ? settings + ".tmp" : settings));
555+
*filepath = fsbridge::AbsPathJoin(GetDataDirNet(), temp ? settings + ".tmp" : settings);
553556
}
554557
return true;
555558
}

src/util/system.h

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -283,16 +283,6 @@ class ArgsManager
283283
*/
284284
const std::map<std::string, std::vector<util::SettingsValue>> GetCommandLineArgs() const;
285285

286-
/**
287-
* Get a normalized path from a specified pathlike argument
288-
*
289-
* It is guaranteed that the returned path has no trailing slashes.
290-
*
291-
* @param pathlike_arg Pathlike argument to get a path from (e.g., "-datadir", "-blocksdir" or "-walletdir")
292-
* @return Normalized path which is get from a specified pathlike argument
293-
*/
294-
fs::path GetPathArg(std::string pathlike_arg) const;
295-
296286
/**
297287
* Get blocks directory path
298288
*
@@ -357,6 +347,18 @@ class ArgsManager
357347
*/
358348
std::string GetArg(const std::string& strArg, const std::string& strDefault) const;
359349

350+
/**
351+
* Return path argument or default value
352+
*
353+
* @param arg Argument to get a path from (e.g., "-datadir", "-blocksdir" or "-walletdir")
354+
* @param default_value Optional default value to return instead of the empty path.
355+
* @return normalized path if argument is set, with redundant "." and ".."
356+
* path components and trailing separators removed (see patharg unit test
357+
* for examples or implementation for details). If argument is empty or not
358+
* set, default_value is returned unchanged.
359+
*/
360+
fs::path GetPathArg(std::string arg, const fs::path& default_value = {}) const;
361+
360362
/**
361363
* Return integer argument or default value
362364
*

0 commit comments

Comments
 (0)