variable-length struct hack

Doug Gwyn gwyn at smoke.BRL.MIL
Fri Dec 8 12:48:16 AEST 1989


In article <15364 at haddock.ima.isc.com> karl at haddock.ima.isc.com (Karl Heuer) writes:
>9.  Hence, strcpy(p->name, s) is legal.

I basically agree with the argument to this point, which is as far as you
took it.  However, the next step might be to access p->name[n], where n > 0,
and that is technically illegal since the `name' member is an array of
length 1, so [0] is the last legally accessible element in it.  A
conforming implementation could, so far as I can tell, enforce bounds
checking on such an array access.  I think Dennis believes that too.

>So it would appear that Doug's implementation of <dirent.h> will work on any
>ANSI C implementation.  Have I overlooked anything?

I think my implementation functions properly internally, for the reasons
you spelled out in deriving conclusion 9 above, but the real question is
whether the user of the dirent facilities can then deal with the struct
dirent to which readdir() returns a pointer in a useful way.  I believe
Dennis is correct in having misgivings about this trickery, not because
the implementation will malfunction, but because in some environments the
struct dirent user might get screwed by this kludge.  (I believe that so
long as he merely uses strcpy() etc. to handle the d_name field, he'll be
okay; it's direct access of the d_name[] elements that might go wrong.)

I don't think IEEE Std 1003.1 guarantees that all the useful information
for a directory entry is contained entirely within the declared struct
dirent type, but it also doesn't warn the user about this issue, so it
is quite likely that somebody will attempt to copy the information using
normal C operations such as
	struct dirent mycopy = *p;
then use the copy, with unpredictable results.  Absent a clear statement
of intent, it is impossible to determine whether this was supposed to
work or not.  From my involvement in thrashing out the dirent specs, my
clear recollection is that the d_name[1] trick was specifically catered
for, meaning that mycopy=*p is not meant to be guaranted to work, but I
admit that this may well come as a surprise to the reader of Std 1003.1
as it now stands.

I think that this whole topic is awfully messy.  I am not "embarrassed"
to have used this trick, for reasons I explained in a previous posting.
However, I do plan on making reliance on the trick an option, rather
than forced, in a future version of my PD dirent implementation.  That
way the installer can, in an environment where array bounds checking is
enforced, decide whether or not to trade off space for user convenience.



More information about the Comp.std.c mailing list