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
2026-02-27 10:41:23 +00:00
3 changed files with 18 additions and 12 deletions

View File

@@ -14,12 +14,6 @@
# 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
# and GCC, without gui.
{
Suppress uninitialized bytes warning in compat code
Memcheck:Param
ioctl(TCSET{S,SW,SF})
fun:tcsetattr
}
{
Suppress leaks on shutdown
Memcheck:Leak

View File

@@ -18,25 +18,38 @@
// https://stackoverflow.com/questions/1413445/reading-a-password-from-stdcin
void SetStdinEcho(bool enable)
{
if (!StdinTerminal()) {
return;
}
#ifdef WIN32
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
GetConsoleMode(hStdin, &mode);
if (!GetConsoleMode(hStdin, &mode)) {
fputs("GetConsoleMode failed\n", stderr);
return;
}
if (!enable) {
mode &= ~ENABLE_ECHO_INPUT;
} else {
mode |= ENABLE_ECHO_INPUT;
}
SetConsoleMode(hStdin, mode);
if (!SetConsoleMode(hStdin, mode)) {
fputs("SetConsoleMode failed\n", stderr);
}
#else
struct termios tty;
tcgetattr(STDIN_FILENO, &tty);
if (tcgetattr(STDIN_FILENO, &tty) != 0) {
fputs("tcgetattr failed\n", stderr);
return;
}
if (!enable) {
tty.c_lflag &= ~ECHO;
tty.c_lflag &= static_cast<decltype(tty.c_lflag)>(~ECHO);
} else {
tty.c_lflag |= ECHO;
}
(void)tcsetattr(STDIN_FILENO, TCSANOW, &tty);
if (tcsetattr(STDIN_FILENO, TCSANOW, &tty) != 0) {
fputs("tcsetattr failed\n", stderr);
}
#endif
}

View File

@@ -55,7 +55,6 @@ unsigned-integer-overflow:TxConfirmStats::EstimateMedianVal
unsigned-integer-overflow:InsecureRandomContext::rand64
unsigned-integer-overflow:InsecureRandomContext::SplitMix64
unsigned-integer-overflow:bitset_detail::PopCount
implicit-integer-sign-change:SetStdinEcho
implicit-integer-sign-change:compressor.h
implicit-integer-sign-change:crypto/
implicit-integer-sign-change:TxConfirmStats::removeTx