take code that is preprocessed and has errors and feed it through ccache, and ccache will use freed memory with path names for example: $ echo 'main(){}' > test.c $ ccache gcc -E test.c -o test.i $ ccache gcc -c test.i $ echo asdf > test.i $ ccache gcc -c test.i gcc: p��: No such file or directory gcc: no input files this is because the global variable "i_tmpfile" is added to orig_args, but when failed() is called, it assumes that the preprocessed file is always an intermediate and not the source, and thus free()'s it. but orig_args->argv still wants to use i_tmpfile in its argv and so when the execve() is called, the string given down is garbage. one fix is to simply avoid the i_tmpfile check in failed() and the associated free() ... this can be seen in gdb by putting a break point on failed(): Breakpoint 1, failed () at ccache.c:100 100 if (i_tmpfile) { (gdb) print orig_args->argv[0]@3 $6 = {0x60f8d0 "/usr/local/src/blackfin/toolchains/20100131/bfin-uclinux/bin/bfin-uclinux-gcc", 0x60f310 "-c", 0x60f2f0 "test.i"} (gdb) print i_tmpfile $7 = 0x60f2f0 "test.i" see how orig_args->argv[2] is pointing to the same storage as i_tmpfile ...
This bug has been fixed as a side-effect of commit befbba943b7d03a1b8e8858e22cb2dfce2ac7935.