From 9e7ecb1b17633369a23a7414b4d7e15f835ee499 Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Wed, 24 Aug 2022 04:01:15 +0100 Subject: [PATCH] Fix freeze on HISTSIZE value exceeding INT_MAX @GabrielRavier writes: > When int is the same as int32_t, starting ksh with > HISTSIZE=2000000000 in the environment (or any number between > 1073741824 and 2147483647) results in an infinite loop, because > of this code: > > if(cp=nv_getval(HISTSIZE)) > maxlines = (unsigned)strtol(cp, (char**)0, 10); > else > maxlines = HIST_DFLT; > for(histmask=16;histmask <= maxlines; histmask <<=1 ); > > which gets stuck infinitely because histmask <= maxlines will > always be true (after 26 iterations, histmask == 1073741824, > after 27 iterations, histmask == -2147483648 and after more than > 28 iterations it's stuck at 0). src/cmd/ksh93/edit/history.c: hist_init(): - Add bounds check for maxlines. HIST_MAX is the number of bytes at which the history file gets cleaned up, so the theoretical maximum number of lines (i.e.: each line being empty, consisting only of a terminating 0 byte) should also be HIST_MAX. That value is 16384 on a system where sizeof(int)==4. Resolves: https://github.com/ksh93/ksh/issues/522 --- NEWS | 5 +++++ src/cmd/ksh93/edit/history.c | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index abf21453f..952624149 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,11 @@ Uppercase BUG_* IDs are shell bug IDs as used by the Modernish shell library. invalid completions if ESC = was used at the beginning of a line. Both tab and = completions are now disabled at the start of the command line. +- Fixed ksh freezing or using excessive memory if HISTSIZE is assigned a + pathologically large value. A new bounds check makes the theoretical + maximum number of history lines equal to the number of bytes kept in the + history file at cleanup time. On 64-bit systems, that maximum is 16384. + 2022-08-20: - Fixed a bug in command line options processing that caused short-form diff --git a/src/cmd/ksh93/edit/history.c b/src/cmd/ksh93/edit/history.c index 574034a84..89c9e5d80 100644 --- a/src/cmd/ksh93/edit/history.c +++ b/src/cmd/ksh93/edit/history.c @@ -257,7 +257,14 @@ retry: /* set the file to close-on-exec */ fcntl(fd,F_SETFD,FD_CLOEXEC); if(cp=nv_getval(HISTSIZE)) - maxlines = (unsigned)strtol(cp, (char**)0, 10); + { + intmax_t m = strtoll(cp, (char**)0, 10); + if(m>HIST_MAX) + m = HIST_MAX; + else if(m<0) + m = HIST_DFLT; + maxlines = (int)m; + } else maxlines = HIST_DFLT; for(histmask=16;histmask <= maxlines; histmask <<=1 );