stratum: do not abort the daemon on a malformed 63-character job_id
The "EWBF 31 bytes job_id fix" in stratum_mining_submit completes a 63-character job_id with each hex digit in turn and feeds the result straight to uint256(). ParseHex() stops at the first non-hex character and returns a shorter vector without signalling an error, and base_blob(const std::vector<unsigned char>&) asserts vch.size() == 32. So a single mining.submit whose job_id is any 63-character string containing a non-hex byte -- 63 spaces will do -- aborts the node. asserts are live in release builds here: -DNDEBUG appears only in leveldb's own makefile, never in configure.ac, and the shipped binary still carries the assertion string. The dispatch loop catches UniValue and std::exception; abort() goes through both. Size-check each candidate before constructing, as ParseUInt256() a few hundred lines up already does for the ordinary path. If none of the 16 completions parse, ret stays null, misses work_templates, and the handler returns false exactly as it does for any unknown job. Not gated on IsHex(job_id_str): 63 is odd and IsHex() requires an even length, so that test would disable the EWBF path this code exists for.
This commit is contained in:
@@ -1334,7 +1334,16 @@ UniValue stratum_mining_submit(StratumClient& client, const UniValue& params)
|
|||||||
if (job_id_str.length() == 63) {
|
if (job_id_str.length() == 63) {
|
||||||
fEWBFJobIDFixNeeded = true;
|
fEWBFJobIDFixNeeded = true;
|
||||||
for(const auto& hexDigit : hexDigits) {
|
for(const auto& hexDigit : hexDigits) {
|
||||||
ret = uint256(ParseHex(job_id_str + hexDigit));
|
// ParseHex() stops at the first non-hex character and returns a SHORT vector
|
||||||
|
// without signalling an error, and base_blob(const std::vector<unsigned char>&)
|
||||||
|
// asserts vch.size() == 32. Constructing without checking therefore lets any
|
||||||
|
// 63-character job_id containing a non-hex byte abort the daemon -- from an
|
||||||
|
// unauthenticated client, before any other validation. Skip bad candidates
|
||||||
|
// instead; if none of the 16 completions parse, ret stays null, misses
|
||||||
|
// work_templates below, and the handler returns false cleanly.
|
||||||
|
std::vector<unsigned char> vch = ParseHex(job_id_str + hexDigit);
|
||||||
|
if (vch.size() != 32) continue;
|
||||||
|
ret = uint256(vch);
|
||||||
if (work_templates.count(ret)) break;
|
if (work_templates.count(ret)) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user