mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Reproducer 1:
$ alias r
r='hist -s'
$ alias r=foo
$ unalias r
ksh(10127,0x10d6c35c0) malloc: *** error for object 0x7ffdcd404468: pointer being freed was not allocated
ksh(10127,0x10d6c35c0) malloc: *** set a breakpoint in malloc_error_break to debug
Abort
The crash happens as unall() (typeset.c) calls nv_delete() (name.c)
which tries to free a node pointer that was not directly allocated.
Reproducer 2:
$ ENV=/./dev/null ksh
$ echo : >script
$ chmod +x script
$ alias r=foo
$ ./script
ksh(10193,0x10c8505c0) malloc: *** error for object 0x7fa136c04468: pointer being freed was not allocated
ksh(10193,0x10c8505c0) malloc: *** set a breakpoint in malloc_error_break to debug
Abort
This crash happens for the same reason, but in another location,
namely in sh_reinit() (init.c) as it is freeing up the alias table
before executing a script that does not start with a #! path.
This is a serious bug because it is not uncommon for .kshrc or
.profile scripts to (re)define an alias called 'r'.
Analysis:
These crashes happen because the incorrectly freed node pointer is
part of a larger block of nodes initialised by sh_inittree() in
init.c. That function allocates all the nodes for a table (see
data/{aliases,builtins,variables}.c) in a contiguous block
addressable by numeric index (see builtins.h and variables.h for
how that is used).
So, while the value of the alias is correctly marked NV_NOFREE and
is not freed, that attribute does not apply to the node pointer
itself, which also is not freeable. Thus, if the value is replaced
by a freeable one, the node pointer is incorrectly freed upon
unaliasing it, and the shell crashes.
The simplest fix is to allocate each predefined alias node
individually, like any other alias -- because, in fact, we do not
need the predefined alias nodes to be in a contiguous addressable
block; there is nothing that specifically addresses these aliases.
src/cmd/ksh93/sh/main.c: sh_main():
- Instead of calling sh_inittree(), use a dedicated loop to
allocate each predefined alias node individually, making each
node invidually freeable. The value does remain non-freeable,
but the NV_NOFREE attribute correctly takes care of that.
src/cmd/ksh93/bltins/typeset.c:
- Get rid of the incomplete and now unnecessary workarounds in
unall() and sh_reinit().
Thanks to @jghub and @JohnoKing for finding and reporting the bug.
Discussion: https://github.com/ksh93/ksh/discussions/503#discussioncomment-3337172
|
||
|---|---|---|
| .. | ||
| cmd | ||
| lib | ||
| Mamfile | ||