bin/121897: [PATCH] realpath(3) segmentation fault

Eric Schuele eric.schuele at computer.org
Thu Mar 20 05:10:02 UTC 2008


>Number:         121897
>Category:       bin
>Synopsis:       [PATCH] realpath(3) segmentation fault
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Mar 20 05:10:01 UTC 2008
>Closed-Date:
>Last-Modified:
>Originator:     Eric Schuele
>Release:        FreeBSD 7.0-STABLE
>Organization:
>Environment:
FreeBSD fangorn.nxdomain.org 7.0-STABLE FreeBSD 7.0-STABLE #0: Wed Mar 12 12:50:03 CDT 2008     root at fangorn.nxdomain.org:/usr/obj/usr/src/sys/CUSTOM  i386
>Description:
The following code seems to behave a little better on linux than FreeBSD 7.0.

#include <stdio.h>
#include <stdlib.h>

main () 
{
  char buf[1024];
  char *s = realpath(NULL, buf);
}

On FreeBSD I get a segmentation fault, while linux gracefully sets errno and goes on with its life.  Do note that changing the above NULL to something a little more sane of course works.

The man page states:
"All but the last component of pathname must exist when realpath() is called."

So, on one hand maybe I was warned. Upon looking at the FreeBSD implementation of realpath(3) its obvious that a null pointer is not acceptable.

Now below is the first few lines of GNU libc's realpath implementation:

  if (name == NULL)
    {
      /* As per Single Unix Specification V2 we must return an error if
         either parameter is a null pointer.  We extend this to allow
         the RESOLVED parameter to be NULL in case the we are expected     	  to allocate the room for the return value.  */
      __set_errno (EINVAL);
      return NULL;
    }

  if (name[0] == '\0')
    {
      /* As per Single Unix Specification V2 we must return an error if
         the name argument points to an empty string.  */
      __set_errno (ENOENT);
      return NULL;
    }

Seems reasonable we should have a similar approach since SUS requests as much.  I have attached a patch which fixes the issue.
>How-To-Repeat:
compile and run the following prog:

#include <stdio.h>
#include <stdlib.h>

main () 
{
  char buf[1024];
  char *s = realpath(NULL, buf);
}
>Fix:
See attached patch.

Patch attached with submission follows:

--- realpath.c.0	2008-03-19 23:50:39.000000000 -0500
+++ realpath.c	2008-03-19 23:50:57.000000000 -0500
@@ -59,6 +59,15 @@
 	int serrno, slen;
 	char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
 
+        if (path == NULL) {
+		errno = EINVAL;
+		return (NULL);
+        }
+        if (path[0] == '\0') {
+		errno = ENOENT;
+		return (NULL);
+        }
+
 	serrno = errno;
 	symlinks = 0;
 	if (path[0] == '/') {


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list