Merge bitcoin/bitcoin#34597: util: Fix UB in SetStdinEcho when ENOTTY

fa6af85634 refactor: Use static_cast<decltype(...)> to suppress integer sanitizer warning (MarcoFalke)
fa692974ac util: Fix UB in SetStdinEcho when ENOTTY (MarcoFalke)

Pull request description:

  The call to `tcgetattr` may fail with `ENOTTY`, leaving the struct possibly uninitialized (UB).

  Fix this UB by returning early when `isatty` fails, or when `tcgetattr` fails. (Same for Windows)

  This can be tested by a command that fails valgrind before the change and passes after:

  ```
  echo 'pipe' | valgrind --quiet ./bld-cmake/bin/bitcoin-cli -stdinrpcpass uptime

ACKs for top commit:
  achow101:
    ACK fa6af85634
  l0rinc:
    lightly tested code review ACK fa6af85634
  sedited:
    ACK fa6af85634

Tree-SHA512: 76e2fbcb6c323b17736ee057dbd5e932b2e8cbb7d9fe4488c1dc7ab6ea928a3cde7e72ca0a63f8c8c78871ccb8b669263b712c0e1b530d88f2d45ea41f071201
This commit is contained in:
merge-script committed 2026-02-27 10:41:23 +00:00
commit 05cd3b00b9
3 files changed
+18 -12

No files matched your search

-6
View File
@@ -14,12 +14,6 @@
# Note that suppressions may depend on OS and/or library versions. # Note that suppressions may depend on OS and/or library versions.
# Tested on aarch64 and x86_64 with Ubuntu Noble system libs, using clang-16 # Tested on aarch64 and x86_64 with Ubuntu Noble system libs, using clang-16
# and GCC, without gui. # and GCC, without gui.
{
Suppress uninitialized bytes warning in compat code
Memcheck:Param
ioctl(TCSET{S,SW,SF})
fun:tcsetattr
}
{ {
Suppress leaks on shutdown Suppress leaks on shutdown
Memcheck:Leak Memcheck:Leak
+18 -5
View File
@@ -18,25 +18,38 @@
// https://stackoverflow.com/questions/1413445/reading-a-password-from-stdcin // https://stackoverflow.com/questions/1413445/reading-a-password-from-stdcin
void SetStdinEcho(bool enable) void SetStdinEcho(bool enable)
{ {
if (!StdinTerminal()) {
return;
}
#ifdef WIN32 #ifdef WIN32
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode; DWORD mode;
GetConsoleMode(hStdin, &mode); if (!GetConsoleMode(hStdin, &mode)) {
fputs("GetConsoleMode failed\n", stderr);
return;
}
if (!enable) { if (!enable) {
mode &= ~ENABLE_ECHO_INPUT; mode &= ~ENABLE_ECHO_INPUT;
} else { } else {
mode |= ENABLE_ECHO_INPUT; mode |= ENABLE_ECHO_INPUT;
} }
SetConsoleMode(hStdin, mode); if (!SetConsoleMode(hStdin, mode)) {
fputs("SetConsoleMode failed\n", stderr);
}
#else #else
struct termios tty; struct termios tty;
tcgetattr(STDIN_FILENO, &tty); if (tcgetattr(STDIN_FILENO, &tty) != 0) {
fputs("tcgetattr failed\n", stderr);
return;
}
if (!enable) { if (!enable) {
tty.c_lflag &= ~ECHO; tty.c_lflag &= static_cast<decltype(tty.c_lflag)>(~ECHO);
} else { } else {
tty.c_lflag |= ECHO; tty.c_lflag |= ECHO;
} }
(void)tcsetattr(STDIN_FILENO, TCSANOW, &tty); if (tcsetattr(STDIN_FILENO, TCSANOW, &tty) != 0) {
fputs("tcsetattr failed\n", stderr);
}
#endif #endif
} }
-1
View File
@@ -55,7 +55,6 @@ unsigned-integer-overflow:TxConfirmStats::EstimateMedianVal
unsigned-integer-overflow:InsecureRandomContext::rand64 unsigned-integer-overflow:InsecureRandomContext::rand64
unsigned-integer-overflow:InsecureRandomContext::SplitMix64 unsigned-integer-overflow:InsecureRandomContext::SplitMix64
unsigned-integer-overflow:bitset_detail::PopCount unsigned-integer-overflow:bitset_detail::PopCount
implicit-integer-sign-change:SetStdinEcho
implicit-integer-sign-change:compressor.h implicit-integer-sign-change:compressor.h
implicit-integer-sign-change:crypto/ implicit-integer-sign-change:crypto/
implicit-integer-sign-change:TxConfirmStats::removeTx implicit-integer-sign-change:TxConfirmStats::removeTx