Skip to content

Commit 24d5cd8

Browse files
authored
Fix memory leak in defpathinit() (#441)
Currently, running ksh under ASan without the ASAN_OPTIONS variable set to 'detect_leaks=0' usually ends with ASan complaining about a memory leak in defpathinit() (this leak doesn't grow in a loop, so no regression test was added to leaks.sh). Reproducer: $ ENV=/dev/null arch/*/bin/ksh $ cp -? cp: invalid option -- '?' Try 'cp --help' for more information. $ exit ================================================================= ==225132==ERROR: LeakSanitizer: detected memory leaks Direct leak of 85 byte(s) in 1 object(s) allocated from: #0 0x7f6dab42d459 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:154 ksh-community#1 0x5647b77fe144 in sh_calloc /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/init.c:265 ksh-community#2 0x5647b788fea9 in path_addcomp /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:1567 ksh-community#3 0x5647b78911ed in path_addpath /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:1705 ksh-community#4 0x5647b7888e82 in defpathinit /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:442 ksh-community#5 0x5647b78869f3 in ondefpath /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:67 --- cut --- SUMMARY: AddressSanitizer: 174 byte(s) leaked in 2 allocation(s). Analysis: The previous code was leaking memory because defpathinit() returns a pointer from path_addpath(), which has memory allocated to it in path_addcomp(). This is the code ASan traced as having allocated memory: 442: return(path_addpath((Pathcomp_t*)0,(defpath),PATH_PATH)); In path_addpath(): 1705: first = path_addcomp(first,old,cp,type); [...] 1729: return(first); In path_addcomp(): 1567: pp = sh_newof((Pathcomp_t*)0,Pathcomp_t,1,len+1); The ondefpath() function doesn't save a reference to the pointer returned by defpathinit(), which causes the memory leak: 66: if(!defpath) 67: defpathinit(); The changes in this commit avoid this problem by setting the defpath variable without also calling path_addpath(). src/cmd/ksh93/sh/path.c: - Move the code for allocating defpath from defpathinit() into its own dedicated function called std_path(). This function is called by defpathinit() and ondefpath() to obtain the current string stored in the defpath variable. This bugfix is adapted from a fork of ksh2020: l0stman/ksh@db5c83a6
1 parent daf483d commit 24d5cd8

File tree

2 files changed

+16
-12
lines changed

2 files changed

+16
-12
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ Any uppercase BUG_* names are modernish shell bug IDs.
99
shell when suspending (Ctrl+Z) an external command invoked by a dot script
1010
or POSIX shell function, or via 'eval'.
1111

12+
- Fixed a memory leak that occurred when running a command that was found on
13+
the PATH.
14+
1215
2022-01-26:
1316

1417
- On Cygwin, ksh now executes scripts that do not have a #! path itself,

src/cmd/ksh93/sh/path.c

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,21 @@ static int checkdotpaths(Pathcomp_t*,Pathcomp_t*,Pathcomp_t*,int);
5858
static void checkdup(register Pathcomp_t*);
5959
static Pathcomp_t *defpathinit(void);
6060

61-
static const char *defpath; /* default path that finds standard utilities */
61+
static const char *std_path(void)
62+
{
63+
static const char *defpath; /* default path that finds standard utilities */
64+
if(!defpath)
65+
{
66+
if(!(defpath = astconf("PATH",NIL(char*),NIL(char*))))
67+
abort();
68+
defpath = sh_strdup(defpath); /* the value returned by astconf() is short-lived */
69+
}
70+
return(defpath);
71+
}
6272

6373
static int ondefpath(const char *name)
6474
{
65-
const char *cp;
66-
if(!defpath)
67-
defpathinit();
68-
cp = defpath;
75+
const char *cp = std_path();
6976
if(cp)
7077
{
7178
const char *sp;
@@ -433,13 +440,7 @@ Pathcomp_t *path_nextcomp(register Pathcomp_t *pp, const char *name, Pathcomp_t
433440

434441
static Pathcomp_t* defpathinit(void)
435442
{
436-
if(!defpath)
437-
{
438-
if(!(defpath = astconf("PATH",NIL(char*),NIL(char*))))
439-
abort();
440-
defpath = sh_strdup(defpath); /* the value returned by astconf() is short-lived */
441-
}
442-
return(path_addpath((Pathcomp_t*)0,(defpath),PATH_PATH));
443+
return(path_addpath((Pathcomp_t*)0,std_path(),PATH_PATH));
443444
}
444445

445446
static void pathinit(void)

0 commit comments

Comments
 (0)