[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
heap-corrupting bug in ftw.c
From: |
Jim Meyering |
Subject: |
heap-corrupting bug in ftw.c |
Date: |
Wed, 05 Feb 2003 18:09:58 +0100 |
When compiling ftw.c on a system like solaris-2.7 (or 2.8 or 2.9, and probably
on the Hurd, too), it turns out that PATH_MAX is not defined here:
#ifdef PATH_MAX
data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX);
#else
data.dirbufsize = 2 * strlen (dir);
#endif
So, when ftw is invoked e.g. with "/", dirbufsize gets a value of `2'.
Then, when process_entry is called, say with `lost+found', it tries
to append that string to `/' in a buffer of length 4. Of course
that results in a buffer overrun.
FWIW, this problem could cause du (from coreutils-4.5.5) to segfault
on Solaris systems.
Here's one way to fix it:
[note that this change conflicts slightly with the one I
sent twice regarding how ftw treats trailing slashes]
2003-02-05 Jim Meyering <address@hidden>
Fix a heap-corrupting bug.
* io/ftw.c: Include <limits.h>.
(PATH_MAX) [!defined PATH_MAX]: Define to 1024.
(process_entry): Allocate enough space to hold the resulting
file name. Don't presume that 2*dirbufsize is enough.
(ftw_startup): Always use PATH_MAX to compute buffer size, now that
it is guaranteed to be defined.
Index: io/ftw.c
===================================================================
RCS file: /cvs/glibc/libc/io/ftw.c,v
retrieving revision 1.39
diff -u -p -r1.39 ftw.c
--- io/ftw.c 2 Feb 2003 21:50:48 -0000 1.39
+++ io/ftw.c 5 Feb 2003 17:01:38 -0000
@@ -29,6 +29,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <limits.h>
#if HAVE_SYS_PARAM_H || defined _LIBC
# include <sys/param.h>
#endif
@@ -41,6 +42,10 @@
/* #define NDEBUG 1 */
#include <assert.h>
+#ifndef PATH_MAX
+# define PATH_MAX 1024
+#endif
+
#ifndef _LIBC
# undef __chdir
# define __chdir chdir
@@ -282,18 +287,20 @@ process_entry (struct ftw_data *data, st
struct STAT st;
int result = 0;
int flag = 0;
+ size_t new_buflen;
if (name[0] == '.' && (name[1] == '\0'
|| (name[1] == '.' && name[2] == '\0')))
/* Don't process the "." and ".." entries. */
return 0;
- if (data->dirbufsize < data->ftw.base + namlen + 2)
+ new_buflen = data->ftw.base + namlen + 2;
+ if (data->dirbufsize < new_buflen)
{
/* Enlarge the buffer. */
char *newp;
- data->dirbufsize *= 2;
+ data->dirbufsize = 2 * new_buflen;
newp = (char *) realloc (data->dirbuf, data->dirbufsize);
if (newp == NULL)
return -1;
@@ -518,11 +525,7 @@ ftw_startup (const char *dir, int is_nft
* sizeof (struct dir_data *));
memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *));
-#ifdef PATH_MAX
data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX);
-#else
- data.dirbufsize = 2 * strlen (dir);
-#endif
data.dirbuf = (char *) malloc (data.dirbufsize);
if (data.dirbuf == NULL)
return -1;
pgpxiv2aMKSiV.pgp
Description: PGP signature
- heap-corrupting bug in ftw.c,
Jim Meyering <=