changeset 16357:fb977cbd79e9

canonicalize: avoid uninitialized memory use When DOUBLE_SLASH_IS_DISTINCT_ROOT is non-zero, then we were reading the contents of rpath[1] even when we had never written anything there, which meant that "///" would usually canonicalize to "/" but sometimes to "//" if a '/' was leftover in the heap. This condition could also occur via 'ln -s / //some/path' and canonicalizing //some/path, where we rewind rpath but do not clear out the previous round. Platforms where "//" and "/" are equivalent do not suffer from this read-beyond-written bounds. * lib/canonicalize-lgpl.c (__realpath): Avoid possibility of random '/' left in dest. * lib/canonicalize.c (canonicalize_filename_mode): Likewise. Signed-off-by: Eric Blake <eblake@redhat.com>
author Eric Blake <eblake@redhat.com>
date Sat, 04 Feb 2012 11:11:40 -0700
parents 2fa8e82affcc
children a712776b11ce
files ChangeLog lib/canonicalize-lgpl.c lib/canonicalize.c
diffstat 3 files changed, 31 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2012-02-04  Eric Blake  <eblake@redhat.com>
+
+	canonicalize: avoid uninitialized memory use
+	* lib/canonicalize-lgpl.c (__realpath): Avoid possibility of
+	random '/' left in dest.
+	* lib/canonicalize.c (canonicalize_filename_mode): Likewise.
+
 2012-02-04  Bruno Haible  <bruno@clisp.org>
 
 	isatty: Fix test failure of ptsname_r on native Windows.
--- a/lib/canonicalize-lgpl.c
+++ b/lib/canonicalize-lgpl.c
@@ -156,8 +156,12 @@
     {
       rpath[0] = '/';
       dest = rpath + 1;
-      if (DOUBLE_SLASH_IS_DISTINCT_ROOT && name[1] == '/' && name[2] != '/')
-        *dest++ = '/';
+      if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
+        {
+          if (name[1] == '/' && name[2] != '/')
+            *dest++ = '/';
+          *dest = '\0';
+        }
     }
 
   for (start = end = name; *start; start = end)
@@ -298,9 +302,12 @@
               if (buf[0] == '/')
                 {
                   dest = rpath + 1;     /* It's an absolute symlink */
-                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT
-                      && buf[1] == '/' && buf[2] != '/')
-                    *dest++ = '/';
+                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
+                    {
+                      if (buf[1] == '/' && buf[2] != '/')
+                        *dest++ = '/';
+                      *dest = '\0';
+                    }
                 }
               else
                 {
--- a/lib/canonicalize.c
+++ b/lib/canonicalize.c
@@ -145,8 +145,12 @@
       rname_limit = rname + PATH_MAX;
       rname[0] = '/';
       dest = rname + 1;
-      if (DOUBLE_SLASH_IS_DISTINCT_ROOT && name[1] == '/' && name[2] != '/')
-        *dest++ = '/';
+      if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
+        {
+          if (name[1] == '/' && name[2] != '/')
+            *dest++ = '/';
+          *dest = '\0';
+        }
     }
 
   for (start = name; *start; start = end)
@@ -267,9 +271,12 @@
               if (buf[0] == '/')
                 {
                   dest = rname + 1;     /* It's an absolute symlink */
-                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT
-                      && buf[1] == '/' && buf[2] != '/')
-                    *dest++ = '/';
+                  if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
+                    {
+                      if (buf[1] == '/' && buf[2] != '/')
+                        *dest++ = '/';
+                      *dest = '\0';
+                    }
                 }
               else
                 {