This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

FreeBSD port (12): wrong use of struct dirent


Hi,

For the FreeBSD port, I decided to use a 'struct dirent' with a d_name array
of length 1, similar to what is suggested by sysdeps/generic/bits/dirent.h.

According to SUSV3 basedefs/dirent.h.html, d_name[] can be of small size:

   "The character array d_name is of unspecified size, but the number of bytes
    preceding the terminating null byte shall not exceed {NAME_MAX}."

And according to SUSV3 functions/readdir.html

   "The storage pointed to by entry shall be large enough for a dirent with an
    array of char d_name members containing at least {NAME_MAX}+1 elements."

which means that it's the responsibility of the caller of readdir_r() to
provide a large enough buffer, i.e. sometimes larger than 'struct dirent'.
The glibc manual's description of readdir_r() says the same thing.

But there is one place in the code and two occurrences in the testsuite
where this rule is not followed.


2002-07-06  Bruno Haible  <bruno@clisp.org>

	* sysdeps/generic/glob.c: Include <limits.h>.
	(NAME_MAX): Define a fallback.
	(glob_in_dir): Allocate enough room for a 'struct dirent64' on the
	stack.
	* posix/tst-dir.c: Include <stddef.h>, for offsetof.
	(main): Allocate enough room for a 'struct dirent64' on the stack.
	* posix/tst-gnuglob.c (my_DIR): Allocate enough room for a
	'struct dirent'.

diff -r -c3 glibc-20020627.bak/sysdeps/generic/glob.c glibc-20020627/sysdeps/generic/glob.c
--- glibc-20020627.bak/sysdeps/generic/glob.c	Sat May  4 00:00:59 2002
+++ glibc-20020627/sysdeps/generic/glob.c	Fri Jul  5 01:17:07 2002
@@ -191,6 +191,14 @@
 
 #endif	/* Standard headers.  */
 
+/* NAME_MAX is usually defined in <dirent.h> or <limits.h>.  */
+#if defined HAVE_LIMITS_H || defined __GNU_LIBRARY__
+# include <limits.h>
+#endif
+#ifndef NAME_MAX
+# define NAME_MAX (sizeof (((struct dirent *) 0)->d_name))
+#endif
+
 #ifndef	ANSI_STRING
 
 # ifndef bzero
@@ -1324,15 +1332,21 @@
 		  size_t len;
 #if defined HAVE_DIRENT64 && !defined COMPILE_GLOB64
 		  struct dirent64 *d;
-		  struct dirent64 d64;
+		  union
+		    {
+		      struct dirent64 d64;
+		      char room [offsetof (struct dirent64, d_name[0])
+				 + NAME_MAX + 1];
+		    }
+		  d64buf;
 
 		  if (flags & GLOB_ALTDIRFUNC)
 		    {
 		      struct dirent *d32 = (*pglob->gl_readdir) (stream);
 		      if (d32 != NULL)
 			{
-			  CONVERT_DIRENT_DIRENT64 (&d64, d32);
-			  d = &d64;
+			  CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32);
+			  d = &d64buf.d64;
 			}
 		      else
 			d = NULL;
diff -r -c3 glibc-20020627.bak/posix/tst-dir.c glibc-20020627/posix/tst-dir.c
--- glibc-20020627.bak/posix/tst-dir.c	Tue Jul 10 22:59:47 2001
+++ glibc-20020627/posix/tst-dir.c	Fri Jul  5 01:17:06 2002
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2000-2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
 
@@ -21,6 +21,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <mcheck.h>
+#include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -48,7 +49,12 @@
   DIR *dir2;
   int result = 0;
   struct dirent64 *d;
-  struct dirent64 direntbuf;
+  union
+    {
+      struct dirent64 d;
+      char room [offsetof (struct dirent64, d_name[0]) + NAME_MAX + 1];
+    }
+    direntbuf;
   char *objdir_copy1;
   char *objdir_copy2;
   char *buf;
@@ -316,7 +322,7 @@
 
   /* Try to find the new directory.  */
   rewinddir (dir1);
-  while (readdir64_r (dir1, &direntbuf, &d) == 0 && d != NULL)
+  while (readdir64_r (dir1, &direntbuf.d, &d) == 0 && d != NULL)
     {
 #ifdef _DIRENT_HAVE_D_TYPE
       if (d->d_type != DT_UNKNOWN && d->d_type != DT_DIR)
@@ -436,7 +442,7 @@
 
   /* We now should have a directory and a file in the new directory.  */
   rewinddir (dir2);
-  while (readdir64_r (dir2, &direntbuf, &d) == 0 && d != NULL)
+  while (readdir64_r (dir2, &direntbuf.d, &d) == 0 && d != NULL)
     {
       if (strcmp (d->d_name, ".") == 0
 	  || strcmp (d->d_name, "..") == 0
diff -r -c3 glibc-20020627.bak/posix/tst-gnuglob.c glibc-20020627/posix/tst-gnuglob.c
--- glibc-20020627.bak/posix/tst-gnuglob.c	Tue Jul 10 22:59:47 2001
+++ glibc-20020627/posix/tst-gnuglob.c	Fri Jul  5 01:17:06 2002
@@ -1,6 +1,6 @@
 /* Test the GNU extensions in glob which allow the user to provide callbacks
    for the filesystem access functions.
-   Copyright (C) 2001 Free Software Foundation, Inc.
+   Copyright (C) 2001-2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
 
@@ -93,6 +93,7 @@
   int level;
   int idx;
   struct dirent d;
+  char room_for_dirent[NAME_MAX];
 } my_DIR;
 
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]