1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-02-15 04:32:24 +00:00

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
This commit is contained in:
Martijn Dekker 2022-08-24 04:01:15 +01:00
parent b6c8bb7b3c
commit 9e7ecb1b17
2 changed files with 13 additions and 1 deletions

5
NEWS
View file

@ -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

View file

@ -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 );