Message ID | 437469fe-7622-9021-0b0c-5e4a1cdb8482@cs.ucla.edu |
---|---|
State | Superseded |
Headers | show |
On Thu, 23 May 2019, Paul Eggert wrote: > On 5/23/19 2:34 AM, Florian Weimer wrote: > > +# ifdef __GNUC__ > > + /* This avoids an unwanted array subscript check by the compiler, > > + while preserving the size of the type. */ > > + __extension__ union > > + { > > + Dl_serpath dls_serpath[0]; /* Actually longer, dls_cnt elements. */ > > + Dl_serpath __dls_serpath_pad[1]; > > + }; > > +# else /* !__GNUC__ */ > > Dl_serpath dls_serpath[1]; /* Actually longer, dls_cnt elements. > > */ > > +# endif /* !__GNUC__ */ > > Since this is actually a flexible array member, shouldn't we be using C99's > support for that if available, instead? Something like the attached untested > patch, say. We've been using a FLEXIBLE_ARRAY_MEMBER macro in Gnulib for quite > some time to do this sort of thing. Since we already have the __flexarr macro in sys/cdefs.h, I don't think having a slightly different __GLIBC_FLEXIBLE_ARRAY_MEMBER as well seems like a good idea.
* Paul Eggert: > On 5/23/19 2:34 AM, Florian Weimer wrote: >> +# ifdef __GNUC__ >> + /* This avoids an unwanted array subscript check by the compiler, >> + while preserving the size of the type. */ >> + __extension__ union >> + { >> + Dl_serpath dls_serpath[0]; /* Actually longer, dls_cnt elements. */ >> + Dl_serpath __dls_serpath_pad[1]; >> + }; >> +# else /* !__GNUC__ */ >> Dl_serpath dls_serpath[1]; /* Actually longer, dls_cnt elements. */ >> +# endif /* !__GNUC__ */ > > Since this is actually a flexible array member, shouldn't we be using > C99's support for that if available, instead? Something like the > attached untested patch, say. We've been using a FLEXIBLE_ARRAY_MEMBER > macro in Gnulib for quite some time to do this sort of thing. This changes the size of the type and is not source-code-compatible. I have not investigated whether the change is still reasonably safe, but usually, wo do not make such changes. Thanks, Florian
On 5/24/19 1:42 AM, Florian Weimer wrote: > This changes the size of the type and is not source-code-compatible. I > have not investigated whether the change is still reasonably safe, but > usually, wo do not make such changes. OK, in that case I suggest adding a comment explaining the situation, since it is a bit of a sore thumb. Something like the following perhaps? Or if this problem is likely to occur elsewhere, we could package the situation up into a macro and just use the macro here. /* An array of dls_cnt elements, each of type Dl_serpath. */ #if 0 /* With no backward-compatibility concerns we’d use the following C99 flexible array member. However, as this data structure predates C99 it had to contain a one-element array here, and we don't want to change the struct's size now. */ Dl_serpath dls_serpath[]; #elif defined __GNUC__ /* Avoid an unwanted array subscript check by the compiler, while preserving the size of the type. */ __extension__ union { Dl_serpath dls_serpath[0]; /* Actually longer, dls_cnt elements. */ Dl_serpath __dls_serpath_pad[1]; }; #else Dl_serpath dls_serpath[1]; #endif
diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h index 896ad6fc9b..01e6fdadc3 100644 --- a/dlfcn/dlfcn.h +++ b/dlfcn/dlfcn.h @@ -180,7 +180,7 @@ typedef struct { size_t dls_size; /* Size in bytes of the whole buffer. */ unsigned int dls_cnt; /* Number of elements in `dls_serpath'. */ - Dl_serpath dls_serpath[1]; /* Actually longer, dls_cnt elements. */ + Dl_serpath dls_serpath[__GLIBC_FLEXIBLE_ARRAY_MEMBER /* dls_cnt */]; } Dl_serinfo; #endif /* __USE_GNU */ diff --git a/include/features.h b/include/features.h index e016b3e5c7..9942984e57 100644 --- a/include/features.h +++ b/include/features.h @@ -141,6 +141,7 @@ #undef __KERNEL_STRICT_NAMES #undef __GLIBC_USE_DEPRECATED_GETS #undef __GLIBC_USE_DEPRECATED_SCANF +#undef __GLIBC_FLEXIBLE_ARRAY_MEMBER /* Suppress kernel-name space pollution unless user expressedly asks for it. */ @@ -423,6 +424,15 @@ # define __GLIBC_USE_DEPRECATED_SCANF 0 #endif +/* 'struct { ...; t m[__GLIBC_FLEXIBLE_ARRAY_MEMBER]; }’ declares a + structure with a flexible array member m at the end in C99 or later, + and a structure with a size-1 array member with earlier compilers. */ +#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __GLIBC_FLEXIBLE_ARRAY_MEMBER +#else +# define __GLIBC_FLEXIBLE_ARRAY_MEMBER 1 +#endif + /* Get definitions of __STDC_* predefined macros, if the compiler has not preincluded this header automatically. */ #include <stdc-predef.h>