Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the defpath memory leak ASan keeps complaining about #441

Merged
merged 1 commit into from
Jan 29, 2022

Conversation

JohnoKing
Copy link

@JohnoKing JohnoKing commented Jan 29, 2022

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
    #1 0x5647b77fe144 in sh_calloc /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/init.c:265
    #2 0x5647b788fea9 in path_addcomp /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:1567
    #3 0x5647b78911ed in path_addpath /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:1705
    #4 0x5647b7888e82 in defpathinit /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:442
    #5 0x5647b78869f3 in ondefpath /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:67
    #6 0x5647b7888225 in checkdup /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:365
    #7 0x5647b7888714 in path_nextcomp /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:403
    #8 0x5647b788b2c0 in path_absolute /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:785
    #9 0x5647b788ad8d in path_search /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:727
    #10 0x5647b78b5549 in sh_exec /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/xec.c:1204
    #11 0x5647b77b8032 in exfile /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/main.c:591
    #12 0x5647b77b5c26 in sh_main /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/main.c:352
    #13 0x5647b77b3ffd in main /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/pmain.c:45
    #14 0x7f6dab0ae6cd in __libc_start_call_main (/usr/lib/libc.so.6+0x2d6cd)

Indirect leak of 89 byte(s) in 1 object(s) allocated from:
    #0 0x7f6dab42d459 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:154
    #1 0x5647b77fe144 in sh_calloc /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/init.c:265
    #2 0x5647b788fea9 in path_addcomp /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:1567
    #3 0x5647b78911ed in path_addpath /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:1705
    #4 0x5647b7888e82 in defpathinit /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:442
    #5 0x5647b78869f3 in ondefpath /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:67
    #6 0x5647b7888225 in checkdup /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:365
    #7 0x5647b7888714 in path_nextcomp /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:403
    #8 0x5647b788b2c0 in path_absolute /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:785
    #9 0x5647b788ad8d in path_search /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:727
    #10 0x5647b78b5549 in sh_exec /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/xec.c:1204
    #11 0x5647b77b8032 in exfile /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/main.c:591
    #12 0x5647b77b5c26 in sh_main /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/main.c:352
    #13 0x5647b77b3ffd in main /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/pmain.c:45
    #14 0x7f6dab0ae6cd in __libc_start_call_main (/usr/lib/libc.so.6+0x2d6cd)

SUMMARY: AddressSanitizer: 174 byte(s) leaked in 2 allocation(s).

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

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
       ksh93#1 0x5647b77fe144 in sh_calloc /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/init.c:265
       ksh93#2 0x5647b788fea9 in path_addcomp /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:1567
       ksh93#3 0x5647b78911ed in path_addpath /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:1705
       ksh93#4 0x5647b7888e82 in defpathinit /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:442
       ksh93#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).

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@db5c83a
@McDutchie
Copy link

This makes no sense. Please explain how this is a memory leak at all.

The string buffer returned by the astconf call should be duplicated, otherwise it will be overwritten. And it's done once at most. There is no point in ever freeing it as the default path string should be kept until the process exits.

As far as I can tell, the new code does exactly the same thing as the old, just in a less straightforward way.

@JohnoKing
Copy link
Author

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:
In defpathinit():

return(path_addpath((Pathcomp_t*)0,(defpath),PATH_PATH));

In path_addpath():
first = path_addcomp(first,old,cp,type);

return(first);

In path_addcomp():
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:

if(!defpath)
defpathinit();

The changes in this pull request avoid this problem by setting the defpath variable without also calling path_addpath().

@McDutchie
Copy link

Thanks for the explanation. So it wasn't complaining about the sh_strdup() call in defpathinit() at all, that makes sense now. And I should have seen that from the trace you posted.

@McDutchie McDutchie merged commit 24d5cd8 into ksh93:dev Jan 29, 2022
@JohnoKing JohnoKing deleted the asan-path-leak branch January 29, 2022 17:37
McDutchie pushed a commit that referenced this pull request Jan 30, 2022
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
     #1 0x5647b77fe144 in sh_calloc /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/init.c:265
     #2 0x5647b788fea9 in path_addcomp /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:1567
     #3 0x5647b78911ed in path_addpath /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:1705
     #4 0x5647b7888e82 in defpathinit /home/johno/GitRepos/KornShell/ksh/src/cmd/ksh93/sh/path.c:442
     #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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants