Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Sun, 24 Jul 2016 15:21:07 -0400
From: Rich Felker <>
Subject: Re: dirname() / basename() - musl vs FreeBSD and OpenBSD

On Sun, Jul 24, 2016 at 09:12:49PM +0200, Daniel Cegiełka wrote:
> Hi,
> I came across a very strange problem when I ports code from OpenBSD to
> musl-libc, and it seems, that a lot of problems can be caused by
> dirname().
> "The dirname() function >>> may <<< modify the string pointed to by
> path, and may return a pointer to static storage that may then be
> overwritten by subsequent calls to dirname()."

There is actually no other option for implementing this function. The
contract does not require that the argument string be a valid pathname
or have a bounded length like PATH_MAX; it operates on general
strings. And "No errors are defined", so failure is not an option. The
only way to implement this function is for it to modify its argument.

> OpenBSD and FreeBSD:
> "dirname() returns a pointer to internal static storage space that
> will be overwritten by subsequent calls (each function has its own
> separate storage).
> Other vendor implementations of dirname() may modify the contents of
> the string passed to dirname(); this should be taken into account when
> writing code which calls this function if portability is desired."
> NetBSD:
> (...)
>      The dirname() function returns a pointer to static storage that
> may be overwritten by subse-
>      quent calls to dirname(). This is not strictly a bug; it is
> explicitly allowed by IEEE Std
>      1003.1-2001 (``POSIX.1'')."

It is a bug because it necessarily returns wrong results for extremely
long strings.

> so:
> #include <libgen.h> /* musl libc dirname() */
> #include <stdio.h>
> int main()
> {
>     char s1[] = "/usr/lib/";
>     char s2[] = "/usr/lib/";
>     char *p1, *p2;
>     p1 = dirname(s1);
>     p2 = openbsd_dirname(s2);
>     printf("musl: s1: %s, p1: %s\n", s1, p1);
>     printf("openbsd_dirname: s2: %s, p2: %s\n", s2, p2);
>     return 0;
> }
> # ./a.out
> musl: s1: /usr, p1: /usr
> openbsd_dirname: s2: /usr/lib/, p2: /usr
> So if you use the code from OpenBSD or FreeBSD, then you should be
> very careful... grep, sed, patch, diff... etc. everything is
> potentially error prone.
> musl has very good support for code from *BSD, so is the ability that
> dirname() in musl does not overwrite argument of the function? It will
> not change anything in relation to the IEEE Std 1003.1-2001, but it
> will be much safer for the code from FreeBSD and OpenBSD.

Not an option, for the above reason.

> btw. the same problem applies to basename():

Same applies there.


Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.