mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-02-15 04:32:24 +00:00
Fix a crashing bug in history expansion
Reproducer: $ set -o histexpand $ echo foo !#^:h !#^:& /usr/local/bin/ksh: :&: no previous substitution ksh(80822,0x10bc2a5c0) malloc: *** error for object 0x10a13bae3: pointer being freed was not allocated ksh(80822,0x10bc2a5c0) malloc: *** set a breakpoint in malloc_error_break to debug Abort Analysis: In hist_expand(), the 'cc' variable has two functions: it holds a pointer to a malloc'ed copy of the current line, and is also used as a temporary pointer with functions like strchr(). After that temporary use, it is set to NULL again, because the 'done:' routine checks if it non-NULL to decide whether to free the pointer. But if an error occurs, the function may jump straight to 'done' without first setting cc to NULL if it had been used as a temporary pointer. It then tries to free an unallocated pointer. src/cmd/ksh93/edit/hexpand.c: hist_expand(): - Eliminate this bad practice by using a separate variable for temporary pointer purposes. (I was unable to reproduce the crash in a pty regression test, though it is consistently reproducible in a real interactive session. So I haven't added that test.)
This commit is contained in:
parent
0a1cc391bf
commit
cda8fc916f
3 changed files with 19 additions and 13 deletions
5
NEWS
5
NEWS
|
@ -3,6 +3,11 @@ For full details, see the git log at: https://github.com/ksh93/ksh/tree/1.0
|
|||
|
||||
Any uppercase BUG_* names are modernish shell bug IDs.
|
||||
|
||||
2022-01-24:
|
||||
|
||||
- Fixed a crashing bug in history expansion that could occur when using the "&"
|
||||
modifier to repeat a substitution while there was no previous substitution.
|
||||
|
||||
2022-01-20:
|
||||
|
||||
- Disallow out-of-range event numbers in history expansion (-H/-o histexpand).
|
||||
|
|
|
@ -147,7 +147,7 @@ int hist_expand(const char *ln, char **xp)
|
|||
*cp, /* current char in ln */
|
||||
*str, /* search string */
|
||||
*evp, /* event/word designator string, for error msgs */
|
||||
*cc=0, /* copy of current line up to cp; temp ptr */
|
||||
*cc=0, /* copy of current line up to cp */
|
||||
hc[3], /* default histchars */
|
||||
*qc="\'\"`"; /* quote characters */
|
||||
Sfio_t *ref=0, /* line referenced by event designator */
|
||||
|
@ -471,8 +471,9 @@ getsel:
|
|||
|
||||
do
|
||||
{
|
||||
cc = strchr(qc, c);
|
||||
q ^= cc ? 1<<(int)(cc - qc) : 0;
|
||||
char *tempcp;
|
||||
tempcp = strchr(qc, c);
|
||||
q ^= tempcp ? 1<<(int)(tempcp - qc) : 0;
|
||||
if(p)
|
||||
sfputc(tmp, c);
|
||||
}
|
||||
|
@ -526,6 +527,7 @@ getsel:
|
|||
/* selected line/words are now in buffer, now go for the modifiers */
|
||||
while(*cp == ':' || (flag & HIST_QUICKSUBST))
|
||||
{
|
||||
char *tempcp;
|
||||
if(flag & HIST_QUICKSUBST)
|
||||
{
|
||||
flag &= ~HIST_QUICKSUBST;
|
||||
|
@ -544,8 +546,8 @@ getsel:
|
|||
c = *++cp;
|
||||
}
|
||||
|
||||
if(cc = strchr(modifiers, c))
|
||||
flag |= mod_flags[cc - modifiers];
|
||||
if(tempcp = strchr(modifiers, c))
|
||||
flag |= mod_flags[tempcp - modifiers];
|
||||
else
|
||||
{
|
||||
errormsg(SH_DICT, ERROR_ERROR, "%c: unrecognized history modifier", c);
|
||||
|
@ -619,14 +621,14 @@ getsel:
|
|||
while(flag & HIST_SUBSTITUTE)
|
||||
{
|
||||
/* find string */
|
||||
if(cc = strstr(str, sb.str[0]))
|
||||
if(tempcp = strstr(str, sb.str[0]))
|
||||
{ /* replace it */
|
||||
c = *cc;
|
||||
*cc = '\0';
|
||||
c = *tempcp;
|
||||
*tempcp = '\0';
|
||||
sfputr(tmp2, str, -1);
|
||||
sfputr(tmp2, sb.str[1], -1);
|
||||
*cc = c;
|
||||
str = cc + strlen(sb.str[0]);
|
||||
*tempcp = c;
|
||||
str = tempcp + strlen(sb.str[0]);
|
||||
}
|
||||
else if(!sftell(tmp2))
|
||||
{ /* not successful */
|
||||
|
@ -640,7 +642,7 @@ getsel:
|
|||
DONE();
|
||||
}
|
||||
/* loop if g modifier specified */
|
||||
if(!cc || !(flag & HIST_GLOBALSUBST))
|
||||
if(!tempcp || !(flag & HIST_GLOBALSUBST))
|
||||
flag &= ~HIST_SUBSTITUTE;
|
||||
}
|
||||
/* output rest of line */
|
||||
|
@ -656,7 +658,6 @@ getsel:
|
|||
tmp = tmp2;
|
||||
tmp2 = 0;
|
||||
}
|
||||
cc = 0;
|
||||
if(*cp)
|
||||
cp++;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#define SH_RELEASE_FORK "93u+m" /* only change if you develop a new ksh93 fork */
|
||||
#define SH_RELEASE_SVER "1.0.0-beta.2" /* semantic version number: https://semver.org */
|
||||
#define SH_RELEASE_DATE "2022-01-20" /* must be in this format for $((.sh.version)) */
|
||||
#define SH_RELEASE_DATE "2022-01-24" /* must be in this format for $((.sh.version)) */
|
||||
#define SH_RELEASE_CPYR "(c) 2020-2022 Contributors to ksh " SH_RELEASE_FORK
|
||||
|
||||
/* Scripts sometimes field-split ${.sh.version}, so don't change amount of whitespace. */
|
||||
|
|
Loading…
Reference in a new issue