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 |