Why does dirname() inside nftw() callback cause abort?
Adhemerval Zanella
adhemerval.zanella@linaro.org
Tue Aug 8 23:35:00 GMT 2017
On 08/08/2017 14:59, john smith wrote:
> The following code doesn't work as expected:
>
> #define _XOPEN_SOURCE 500
> #include <ftw.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <libgen.h>
> #include <unistd.h>
> #include <errno.h>
>
> static int display_info(const char *fpath, const struct stat *sb,
> int tflag, struct FTW *ftwbuf)
> {
> (void)sb;
> (void)tflag;
> (void)ftwbuf;
>
> char *dir = dirname((char *) fpath);
> return 0; /* To tell nftw() to continue */
> }
Because you are tampering with a buffer which is not supposed to be
changed by the callback (the necessity to cast to char * should have
hinted you about it). To use dirname you will need to actually make
a copy of the input argument:
[...]
char *path = strdup (fpath);
char *dir = dirname (path);
/* Do something with dir. */
free (path);
[...]
>
> int usb_device_list_get(void)
> {
> int flags = 0;
>
> if (nftw("/sys/bus/usb/devices", display_info, 20, flags)
> == -1) {
> perror("Traversing /sys/bus/usb/devices failed");
> return errno;
> }
>
> return 0;
> }
>
> int main(void)
> {
> usb_device_list_get();
> return EXIT_SUCCESS;
> }
>
> $ ./usb
> usb: ../sysdeps/wordsize-64/../../io/ftw.c:536: ftw_dir: Assertion
> `startp != data->dirbuf' failed.
> Aborted
> $ echo $?
> 134
>
> It's just an example, it is a part of a bigger project when dirname()
> output is actually used.
>
> It only crashes on x64 system, it works well on x32. Man nftw
> mentions:
It is working on x32 just by chance in your system, on mine (ubuntu 16)
it fails on all x86 abis (x86_64, x86_64-x32, and i686).
>
> "POSIX.1-2008 notes that the results are unspecified if fn does not
> preserve the current working directory."
>
> IIUC, it refers to the working directory that can be checked with
> getcwd() - I checked that dirname() does not change it.
>
> glibc version:
>
> GNU C Library (GNU libc) stable release version 2.26, by Roland McGrath et al.
> Copyright (C) 2017 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions.
> There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
> PARTICULAR PURPOSE.
> Compiled by GNU CC version 7.1.0.
> Available extensions:
> crypt add-on version 2.1 by Michael Glad and others
> GNU Libidn by Simon Josefsson
> Native POSIX Threads Library by Ulrich Drepper et al
> BIND-8.2.3-T5B
> libc ABIs: UNIQUE IFUNC
>
> OS:
>
> Slackware Linux -current x64
>
More information about the Libc-help
mailing list