Bug 10913 - Setting CCACHE_DIR to null string results in "ccache -s" segmentation fault.
Setting CCACHE_DIR to null string results in "ccache -s" segmentation fault.
Product: ccache
Classification: Unclassified
Component: ccache
x64 Linux
: P5 major
: 3.2
Assigned To: Joel Rosdahl
Joel Rosdahl
Depends on:
  Show dependency treegraph
Reported: 2014-11-02 08:24 UTC by ishikawa
Modified: 2014-11-17 19:25 UTC (History)
0 users

See Also:


Note You need to log in before you can comment on or make changes to this bug.
Description ishikawa 2014-11-02 08:24:06 UTC

Please see the following.
If someone sets CCACHE_DIR to an empty / null string,
ccache -s
results in a segmentation fault.
It seems create_parent_dirs() is called infinite times since it seems to create
a parent of "/" infinite times and stack overflows, or something.

This happens with git trunk (don't be misled by the directory name below in the
shell prompt.)

ishikawa@ip030:/home/ishikawa/repos/ccache-gsplit-dwarf-support$ export CCACHE_DIR=
ishikawa@ip030:/home/ishikawa/repos/ccache-gsplit-dwarf-support$ ./ccache -s
Segmentation fault

ishikawa@ip030:/home/ishikawa/repos/ccache-gsplit-dwarf-support$ gdb ./ccache
GNU gdb (Debian 7.7.1+dfsg-3) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
Find the GDB manual and other documentation resources online at:
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./ccache...done.
(gdb) run -s
Starting program: /home/ishikawa/repos/ccache-gsplit-dwarf-support/ccache -s

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7591ca5 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) where
#0  0x00007ffff7591ca5 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007ffff7593e20 in malloc () from /lib/x86_64-linux-gnu/libc.so.6
#2  0x00007ffff759978a in strdup () from /lib/x86_64-linux-gnu/libc.so.6
#3  0x0000000000409019 in x_strdup (s=s@entry=0x5a1d30 "/ccache.conf")
    at util.c:620
#4  0x0000000000409376 in dirname (path=path@entry=0x5a1d30 "/ccache.conf")
    at util.c:809
#5  0x00000000004093d0 in create_parent_dirs (
    path=path@entry=0x5a1d30 "/ccache.conf") at util.c:473
#6  0x000000000040941d in create_parent_dirs (
    path=path@entry=0x5a1d10 "/ccache.conf") at util.c:483
#7  0x000000000040941d in create_parent_dirs (
    path=path@entry=0x5a1cf0 "/ccache.conf") at util.c:483
#8  0x000000000040941d in create_parent_dirs (
    path=path@entry=0x5a1cd0 "/ccache.conf") at util.c:483
#9  0x000000000040941d in create_parent_dirs (
    path=path@entry=0x5a1cb0 "/ccache.conf") at util.c:483
#10 0x000000000040941d in create_parent_dirs (
    path=path@entry=0x5a1c90 "/ccache.conf") at util.c:483

   ... well, no end in sight: I had to suspend gdb and killed it. ...

I set a break point and tried again.

Type "apropos word" to search for commands related to "word".
Command name abbreviations are allowed if unambiguous.
(gdb) help set environment
Set environment variable value to give the program.
Arguments are VAR VALUE where VAR is variable name and VALUE is value.
VALUES of environment variables are uninterpreted strings.
This does not affect the program until the next "run" command.
(gdb) break create_parent_dirs
Breakpoint 1 at 0x409460: file util.c, line 470.
(gdb) set CCACHE_DIR
No symbol "CCACHE_DIR" in current context.
(gdb) set environment CCACHE_DIR
Undefined command: "setenvironment".  Try "help".
(gdb) set environment CCACHE_DIR
Setting environment variable "CCACHE_DIR" to null value.
(gdb) run -s
Starting program: /home/ishikawa/repos/ccache-gsplit-dwarf-support/ccache -s

Breakpoint 1, create_parent_dirs (path=path@entry=0x41f410 "/ccache.conf")
    at util.c:470
470	{
(gdb) list
465	}
467	/* Create directories leading to path. Returns 0 on success, otherwise -1. */
468	int
469	create_parent_dirs(const char *path)
470	{
471		struct stat st;
472		int res;
473		char *parent = dirname(path);
(gdb) where
#0  create_parent_dirs (path=path@entry=0x41f410 "/ccache.conf") at util.c:470
#1  0x0000000000404115 in create_initial_config_file (
    path=0x41f410 "/ccache.conf", conf=0x41f030) at ccache.c:2973
#2  initialize () at ccache.c:3058
#3  0x0000000000407625 in ccache_main_options (argv=<optimized out>, 
    argc=<optimized out>) at ccache.c:3448
#4  ccache_main (argc=2, argv=0x7fffffffd9b8) at ccache.c:3484
#5  0x00007ffff7539b45 in __libc_start_main ()
   from /lib/x86_64-linux-gnu/libc.so.6
#6  0x0000000000403eee in _start ()
(gdb) up
#1  0x0000000000404115 in create_initial_config_file (
    path=0x41f410 "/ccache.conf", conf=0x41f030) at ccache.c:2973
2973		if (create_parent_dirs(path) != 0) {
(gdb) list
2968		uint64_t max_size;
2969		char *stats_dir;
2970		FILE *f;
2971		struct stat st;
2973		if (create_parent_dirs(path) != 0) {
2974			return;
2975		}
2977		stats_dir = format("%s/0", conf->cache_dir);
(gdb) print path
$1 = 0x41f410 "/ccache.conf"
(gdb) quit
A debugging session is active.

I think special handling of cases

- where the directory  is "/", or
- where the directory is write protected

may be required to here.
(I hate to think what would have happened if I run ccache 
with null CCACHE_DIR in superuser account by mistake ...)

Or simply barfing out "CCACHE_DIR is null. Set it to a proper value." and
bailing out is a way to go.

Comment 1 Joel Rosdahl 2014-11-15 15:18:42 UTC
Fixed in 136d76854c93a36491a0906e835490ad6927cf47 on master.
Comment 2 Joel Rosdahl 2014-11-17 19:25:03 UTC
Included in v3.2.