Skip to content

Commit 68ef952

Browse files
committed
Merge #18413: script: prevent UB when computing abs value for num opcode serialize
2748e87 script: prevent UB when computing abs value for num opcode serialize (pierrenn) Pull request description: This was reported by practicalswift here #18046 It seems that the original author of the line used a reference to glibc `abs`: https://github.com/lattera/glibc/blob/master/stdlib/abs.c However depending on some implementation details this can be undefined behavior for unusual values. A detailed explanation of the UB is provided here : https://stackoverflow.com/questions/17313579/is-there-a-safe-way-to-get-the-unsigned-absolute-value-of-a-signed-integer-with (by [Billy O'Neal](https://twitter.com/malwareminigun)) Simple relevant godbolt example : https://godbolt.org/z/yRwtCG Thanks! ACKs for top commit: sipa: ACK 2748e87 MarcoFalke: ACK 2748e87, only checked that the bitcoind binary does not change with clang -O2 🎓 practicalswift: ACK 2748e87 Tree-SHA512: 539a34c636c2674c66cb6e707d9d0dfdce63f59b5525610ed88da10c9a8d59d81466b111ad63b850660cef3750d732fc7755530c81a2d61f396be0707cd86dec
2 parents 844d207 + 2748e87 commit 68ef952

File tree

3 files changed

+3
-11
lines changed

3 files changed

+3
-11
lines changed

src/script/script.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ class CScriptNum
329329

330330
std::vector<unsigned char> result;
331331
const bool neg = value < 0;
332-
uint64_t absvalue = neg ? -value : value;
332+
uint64_t absvalue = neg ? ~static_cast<uint64_t>(value) + 1 : static_cast<uint64_t>(value);
333333

334334
while(absvalue)
335335
{

src/test/fuzz/integer.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
148148

149149
const CScriptNum script_num{i64};
150150
(void)script_num.getint();
151-
// Avoid negation failure:
152-
// script/script.h:332:35: runtime error: negation of -9223372036854775808 cannot be represented in type 'int64_t' (aka 'long'); cast to an unsigned type to negate this value to itself
153-
if (script_num != CScriptNum{std::numeric_limits<int64_t>::min()}) {
154-
(void)script_num.getvch();
155-
}
151+
(void)script_num.getvch();
156152

157153
const arith_uint256 au256 = UintToArith256(u256);
158154
assert(ArithToUint256(au256) == u256);

src/test/fuzz/scriptnum_ops.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,6 @@ void test_one_input(const std::vector<uint8_t>& buffer)
129129
break;
130130
}
131131
(void)script_num.getint();
132-
// Avoid negation failure:
133-
// script/script.h:332:35: runtime error: negation of -9223372036854775808 cannot be represented in type 'int64_t' (aka 'long'); cast to an unsigned type to negate this value to itself
134-
if (script_num != CScriptNum{std::numeric_limits<int64_t>::min()}) {
135-
(void)script_num.getvch();
136-
}
132+
(void)script_num.getvch();
137133
}
138134
}

0 commit comments

Comments
 (0)