debloat realpath's allocation strategy
authorRich Felker <dalias@aerifal.cx>
Sat, 31 Aug 2013 19:50:23 +0000 (15:50 -0400)
committerRich Felker <dalias@aerifal.cx>
Sat, 31 Aug 2013 19:50:23 +0000 (15:50 -0400)
rather than allocating a PATH_MAX-sized buffer when the caller does
not provide an output buffer, work first with a PATH_MAX-sized temp
buffer with automatic storage, and either copy it to the caller's
buffer or strdup it on success. this not only avoids massive memory
waste, but also avoids pulling in free (and thus the full malloc
implementation) unnecessarily in static programs.

src/misc/realpath.c

index 2b84649716b4bc08f004b0707f6ed44f20c3aa5f..43d4018358f718c69455192930ec73ffe540e4de 100644 (file)
@@ -5,6 +5,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
+#include <string.h>
 
 void __procfdname(char *, unsigned);
 
@@ -14,7 +15,7 @@ char *realpath(const char *restrict filename, char *restrict resolved)
        ssize_t r;
        struct stat st1, st2;
        char buf[15+3*sizeof(int)];
-       int alloc = 0;
+       char tmp[PATH_MAX];
 
        if (!filename) {
                errno = EINVAL;
@@ -25,27 +26,20 @@ char *realpath(const char *restrict filename, char *restrict resolved)
        if (fd < 0) return 0;
        __procfdname(buf, fd);
 
-       if (!resolved) {
-               alloc = 1;
-               resolved = malloc(PATH_MAX);
-               if (!resolved) return 0;
-       }
-
-       r = readlink(buf, resolved, PATH_MAX-1);
+       r = readlink(buf, tmp, sizeof tmp - 1);
        if (r < 0) goto err;
-       resolved[r] = 0;
+       tmp[r] = 0;
 
        fstat(fd, &st1);
-       r = stat(resolved, &st2);
+       r = stat(tmp, &st2);
        if (r<0 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
                if (!r) errno = ELOOP;
                goto err;
        }
 
        close(fd);
-       return resolved;
+       return resolved ? strcpy(resolved, tmp) : strdup(tmp);
 err:
-       if (alloc) free(resolved);
        close(fd);
        return 0;
 }