Compiling with gcc (15.2.1; x86_64; Arch Linux) gives these warnings about dangling pointers in run in tmpfiles.c:
../src/tmpfiles/tmpfiles.c: In function ‘run’:
../src/tmpfiles/tmpfiles.c:5578:24: warning: dangling pointer ‘config_dirs’ to an unnamed temporary may be used [-Wdangling-pointer=]
5578 | return cat_config(config_dirs, argv + optind);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/shared/macro.h:367:51: note: unnamed temporary defined here
367 | #define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
| ^
../src/shared/constants.h:11:9: note: in expansion of macro ‘STRV_MAKE’
11 | STRV_MAKE(CONF_PATHS_USR(n))
| ^~~~~~~~~
../src/tmpfiles/tmpfiles.c:5553:31: note: in expansion of macro ‘CONF_PATHS_STRV’
5553 | config_dirs = CONF_PATHS_STRV("tmpfiles.d");
| ^~~~~~~~~~~~~~~
../src/tmpfiles/tmpfiles.c:5598:21: warning: dangling pointer ‘config_dirs’ to an unnamed temporary may be used [-Wdangling-pointer=]
5598 | r = read_config_files(&c, config_dirs, argv + optind, &invalid_config);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/shared/macro.h:367:51: note: unnamed temporary defined here
367 | #define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
| ^
../src/shared/constants.h:11:9: note: in expansion of macro ‘STRV_MAKE’
11 | STRV_MAKE(CONF_PATHS_USR(n))
| ^~~~~~~~~
../src/tmpfiles/tmpfiles.c:5553:31: note: in expansion of macro ‘CONF_PATHS_STRV’
5553 | config_dirs = CONF_PATHS_STRV("tmpfiles.d");
| ^~~~~~~~~~~~~~~
../src/tmpfiles/tmpfiles.c:5600:21: warning: dangling pointer ‘config_dirs’ to an unnamed temporary may be used [-Wdangling-pointer=]
5600 | r = parse_arguments(&c, config_dirs, argv + optind, &invalid_config);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/shared/macro.h:367:51: note: unnamed temporary defined here
367 | #define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
| ^
../src/shared/constants.h:11:9: note: in expansion of macro ‘STRV_MAKE’
11 | STRV_MAKE(CONF_PATHS_USR(n))
| ^~~~~~~~~
../src/tmpfiles/tmpfiles.c:5553:31: note: in expansion of macro ‘CONF_PATHS_STRV’
5553 | config_dirs = CONF_PATHS_STRV("tmpfiles.d");
| ^~~~~~~~~~~~~~~
../src/shared/macro.h:117:37: warning: dangling pointer ‘config_dirs’ to an unnamed temporary may be used [-Wdangling-pointer=]
117 | #define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
| ^~~~~~~~~~~~~~~~
../src/shared/string-util.h:44:32: note: in definition of macro ‘_STRV_FOREACH’
44 | for (typeof(*(l)) *s, *i = (l); (s = i) && *i; i++)
| ^
../src/shared/macro.h:103:27: note: in expansion of macro ‘XCONCATENATE’
103 | #define CONCATENATE(x, y) XCONCATENATE(x, y)
| ^~~~~~~~~~~~
../src/shared/macro.h:117:25: note: in expansion of macro ‘CONCATENATE’
117 | #define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
| ^~~~~~~~~~~
../src/shared/string-util.h:47:29: note: in expansion of macro ‘UNIQ_T’
47 | _STRV_FOREACH(s, l, UNIQ_T(i, UNIQ))
| ^~~~~~
../src/tmpfiles/tmpfiles.c:5563:17: note: in expansion of macro ‘STRV_FOREACH’
5563 | STRV_FOREACH(i, config_dirs) {
| ^~~~~~~~~~~~
../src/shared/macro.h:367:51: note: unnamed temporary defined here
367 | #define STRV_MAKE(...) ((char**) ((const char*[]) { __VA_ARGS__, NULL }))
| ^
../src/shared/constants.h:11:9: note: in expansion of macro ‘STRV_MAKE’
11 | STRV_MAKE(CONF_PATHS_USR(n))
| ^~~~~~~~~
../src/tmpfiles/tmpfiles.c:5553:31: note: in expansion of macro ‘CONF_PATHS_STRV’
5553 | config_dirs = CONF_PATHS_STRV("tmpfiles.d");
| ^~~~~~~~~~~~~~~
When building with -O1 or higher (meson setup build -Dc_args="-O1 -g") tmpfiles segfaults when run. E.g. build/src/tmpfiles/sd-tmpfiles --cat-config. Building with sanitizers (meson setup --wipe build -Dc_args="-O1 -g -fsanitize=undefined,address" -Dc_link_args="-lasan -lubsan") results in this use-after-scope error for that invocation:
==3094829==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7bc637e003a0 at pc 0x557fa5f80abc bp 0x7ffc53a21540 sp 0x7ffc53a21530
READ of size 8 at 0x7bc637e003a0 thread T0
#0 0x557fa5f80abb in conf_files_list_strv ../src/shared/conf-files.c:110
#1 0x557fa5f80abb in conf_files_list_with_replacement ../src/shared/conf-files.c:220
#2 0x557fa5f6ec75 in cat_config ../src/tmpfiles/tmpfiles.c:5122
#3 0x557fa5f6ec75 in run ../src/tmpfiles/tmpfiles.c:5578
#4 0x557fa5f6ec75 in main ../src/tmpfiles/tmpfiles.c:5663
#5 0x7fc63a027634 (/usr/lib/libc.so.6+0x27634) (BuildId: 9569a499070da747128b450e157301b26f5c2f9c)
#6 0x7fc63a0276e8 in __libc_start_main (/usr/lib/libc.so.6+0x276e8) (BuildId: 9569a499070da747128b450e157301b26f5c2f9c)
#7 0x557fa5f42ca4 in _start (/home/wmoore/Source/github.com/chimera-linux/sd-tools/build/src/tmpfiles/sd-tmpfiles+0x80ca4) (BuildId: 8f19f6c0ca3a003d7a2e732c0a8c7d84a6028e2d)
Address 0x7bc637e003a0 is located in stack of thread T0 at offset 928 in frame
#0 0x557fa5f6cfe6 in main ../src/tmpfiles/tmpfiles.c:5657
This frame has 29 object(s):
[32, 33) 'invalid_config' (line 5485)
[48, 56) 'config_dirsp' (line 5482)
[80, 88) 'a' (line 5486)
[112, 120) 't' (line 5561)
[144, 152) 'j' (line 5564)
[176, 184) 'config_dirs' (line 662)
[208, 216) 'data_dirs' (line 662)
[240, 248) 'persistent_config' (line 663)
[272, 280) 'runtime_config' (line 663)
[304, 312) 'data_home' (line 663)
[336, 344) 'res' (line 664)
[368, 376) 'config_dirs' (line 630)
[400, 408) 'data_dirs' (line 630)
[432, 440) 'ret'
[464, 472) 'ret'
[496, 504) 'j' (line 566)
[528, 536) 'j' (line 591)
[560, 568) 'files' (line 5119)
[592, 600) 'files' (line 5417)
[624, 632) 'p' (line 5418)
[656, 672) 'rlim' (line 5494)
[688, 704) 'highest' (line 5531)
[720, 736) '__unique_prefix_i19' (line 5605)
[752, 768) '__unique_prefix_i20' (line 5610)
[784, 800) '__unique_prefix_i21' (line 5634)
[816, 832) '__unique_prefix_i22' (line 5641)
[848, 888) 'c' (line 5483)
[928, 968) '<unknown>' <== Memory access at offset 928 is inside this variable
[1008, 1048) '<unknown>'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope ../src/shared/conf-files.c:110 in conf_files_list_strv
Shadow bytes around the buggy address:
0x7bc637e00100: f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2
0x7bc637e00180: f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2
0x7bc637e00200: f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2
0x7bc637e00280: f2 f2 00 00 f2 f2 00 00 f2 f2 00 00 f2 f2 00 00
0x7bc637e00300: f2 f2 00 00 f2 f2 00 00 f2 f2 00 00 00 00 00 f2
=>0x7bc637e00380: f2 f2 f2 f2[f8]f8 f8 f8 f8 f2 f2 f2 f2 f2 00 00
0x7bc637e00400: 00 00 00 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00
0x7bc637e00480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7bc637e00500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7bc637e00580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7bc637e00600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==3094829==ABORTING
Replicating this with clang does not trigger the sanitizer. It does also happen with gcc 14 (14.3.1) though. Similar results are also achieved with other invocations like build/src/tmpfiles/sd-tmpfiles --create --dry-run.
AddressSanitizer: stack-use-after-scope ../src/shared/conf-files.c:110 in conf_files_list_strv
==3339842==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7b5c346003a0 at pc 0x55b3abeefabc bp 0x7ffdeab803b0 sp 0x7ffdeab803a0
READ of size 8 at 0x7b5c346003a0 thread T0
#0 0x55b3abeefabb in conf_files_list_strv ../src/shared/conf-files.c:110
#1 0x55b3abeefabb in conf_files_list_with_replacement ../src/shared/conf-files.c:220
#2 0x55b3abedddcf in read_config_files ../src/tmpfiles/tmpfiles.c:5423
#3 0x55b3abedddcf in run ../src/tmpfiles/tmpfiles.c:5598
#4 0x55b3abedddcf in main ../src/tmpfiles/tmpfiles.c:5663
#5 0x7f5c36827634 (/usr/lib/libc.so.6+0x27634) (BuildId: 9569a499070da747128b450e157301b26f5c2f9c)
#6 0x7f5c368276e8 in __libc_start_main (/usr/lib/libc.so.6+0x276e8) (BuildId: 9569a499070da747128b450e157301b26f5c2f9c)
#7 0x55b3abeb1ca4 in _start (/home/wmoore/Source/github.com/chimera-linux/sd-tools/build/src/tmpfiles/sd-tmpfiles+0x80ca4) (BuildId: 8f19f6c0ca3a003d7a2e732c0a8c7d84a6028e2d)
Address 0x7b5c346003a0 is located in stack of thread T0 at offset 928 in frame
#0 0x55b3abedbfe6 in main ../src/tmpfiles/tmpfiles.c:5657
This frame has 29 object(s):
[32, 33) 'invalid_config' (line 5485)
[48, 56) 'config_dirsp' (line 5482)
[80, 88) 'a' (line 5486)
[112, 120) 't' (line 5561)
[144, 152) 'j' (line 5564)
[176, 184) 'config_dirs' (line 662)
[208, 216) 'data_dirs' (line 662)
[240, 248) 'persistent_config' (line 663)
[272, 280) 'runtime_config' (line 663)
[304, 312) 'data_home' (line 663)
[336, 344) 'res' (line 664)
[368, 376) 'config_dirs' (line 630)
[400, 408) 'data_dirs' (line 630)
[432, 440) 'ret'
[464, 472) 'ret'
[496, 504) 'j' (line 566)
[528, 536) 'j' (line 591)
[560, 568) 'files' (line 5119)
[592, 600) 'files' (line 5417)
[624, 632) 'p' (line 5418)
[656, 672) 'rlim' (line 5494)
[688, 704) 'highest' (line 5531)
[720, 736) '__unique_prefix_i19' (line 5605)
[752, 768) '__unique_prefix_i20' (line 5610)
[784, 800) '__unique_prefix_i21' (line 5634)
[816, 832) '__unique_prefix_i22' (line 5641)
[848, 888) 'c' (line 5483)
[928, 968) '<unknown>' <== Memory access at offset 928 is inside this variable
[1008, 1048) '<unknown>'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions are supported)
SUMMARY: AddressSanitizer: stack-use-after-scope ../src/shared/conf-files.c:110 in conf_files_list_strv
Shadow bytes around the buggy address:
0x7b5c34600100: f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2
0x7b5c34600180: f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2
0x7b5c34600200: f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2
0x7b5c34600280: f2 f2 00 00 f2 f2 00 00 f2 f2 00 00 f2 f2 00 00
0x7b5c34600300: f2 f2 00 00 f2 f2 00 00 f2 f2 00 00 00 00 00 f2
=>0x7b5c34600380: f2 f2 f2 f2[f8]f8 f8 f8 f8 f2 f2 f2 f2 f2 00 00
0x7b5c34600400: 00 00 00 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00
0x7b5c34600480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7b5c34600500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7b5c34600580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7b5c34600600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==3339842==ABORTING
Compiling with
gcc(15.2.1; x86_64; Arch Linux) gives these warnings about dangling pointers inrunintmpfiles.c:When building with
-O1or higher (meson setup build -Dc_args="-O1 -g")tmpfilessegfaults when run. E.g.build/src/tmpfiles/sd-tmpfiles --cat-config. Building with sanitizers (meson setup --wipe build -Dc_args="-O1 -g -fsanitize=undefined,address" -Dc_link_args="-lasan -lubsan") results in thisuse-after-scopeerror for that invocation:Replicating this with
clangdoes not trigger the sanitizer. It does also happen with gcc 14 (14.3.1) though. Similar results are also achieved with other invocations likebuild/src/tmpfiles/sd-tmpfiles --create --dry-run.AddressSanitizer: stack-use-after-scope ../src/shared/conf-files.c:110 in conf_files_list_strv
==3339842==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7b5c346003a0 at pc 0x55b3abeefabc bp 0x7ffdeab803b0 sp 0x7ffdeab803a0 READ of size 8 at 0x7b5c346003a0 thread T0 #0 0x55b3abeefabb in conf_files_list_strv ../src/shared/conf-files.c:110 #1 0x55b3abeefabb in conf_files_list_with_replacement ../src/shared/conf-files.c:220 #2 0x55b3abedddcf in read_config_files ../src/tmpfiles/tmpfiles.c:5423 #3 0x55b3abedddcf in run ../src/tmpfiles/tmpfiles.c:5598 #4 0x55b3abedddcf in main ../src/tmpfiles/tmpfiles.c:5663 #5 0x7f5c36827634 (/usr/lib/libc.so.6+0x27634) (BuildId: 9569a499070da747128b450e157301b26f5c2f9c) #6 0x7f5c368276e8 in __libc_start_main (/usr/lib/libc.so.6+0x276e8) (BuildId: 9569a499070da747128b450e157301b26f5c2f9c) #7 0x55b3abeb1ca4 in _start (/home/wmoore/Source/github.com/chimera-linux/sd-tools/build/src/tmpfiles/sd-tmpfiles+0x80ca4) (BuildId: 8f19f6c0ca3a003d7a2e732c0a8c7d84a6028e2d)
Address 0x7b5c346003a0 is located in stack of thread T0 at offset 928 in frame
#0 0x55b3abedbfe6 in main ../src/tmpfiles/tmpfiles.c:5657
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions are supported)
SUMMARY: AddressSanitizer: stack-use-after-scope ../src/shared/conf-files.c:110 in conf_files_list_strv
Shadow bytes around the buggy address:
0x7b5c34600100: f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2
0x7b5c34600180: f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2
0x7b5c34600200: f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2 f2 f2 00 f2
0x7b5c34600280: f2 f2 00 00 f2 f2 00 00 f2 f2 00 00 f2 f2 00 00
0x7b5c34600300: f2 f2 00 00 f2 f2 00 00 f2 f2 00 00 00 00 00 f2
=>0x7b5c34600380: f2 f2 f2 f2[f8]f8 f8 f8 f8 f2 f2 f2 f2 f2 00 00
0x7b5c34600400: 00 00 00 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00
0x7b5c34600480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7b5c34600500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7b5c34600580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7b5c34600600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==3339842==ABORTING