Message ID | 87a7ey8ytd.fsf@oldenburg2.str.redhat.com |
---|---|
State | New |
Headers | show |
Series | dlfcn: Avoid one-element flexible array in Dl_serinfo | expand |
* Florian Weimer: > The dls_serpath path field, as an array of length 1, introduces > unexpected array subscript checks with some compilers. > > GCC versions before 3.0 treat the nested anonymous union as a > declaration of an unnamed type, and not as a member declaration, > so this construct cannot be used for these compilers. > > 2019-06-03 Florian Weimer <fweimer@redhat.com> > > [BZ #24166] > * dlfcn/dlfcn.h (Dl_serinfo): Do not use array of length 1 for > dls_serpath field. > > diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h > index 896ad6fc9b..c550371999 100644 > --- a/dlfcn/dlfcn.h > +++ b/dlfcn/dlfcn.h > @@ -180,7 +180,19 @@ typedef struct > { > size_t dls_size; /* Size in bytes of the whole buffer. */ > unsigned int dls_cnt; /* Number of elements in `dls_serpath'. */ > +# if __GNUC_PREREQ (3, 0) > + /* The zero-length array avoids an unwanted array subscript check by > + the compiler, while the surrounding anonymous union preserves the > + historic size of the type. At the time of writing, GNU C does > + not support structs with flexible array members in unions. */ > + __extension__ union > + { > + Dl_serpath dls_serpath[0]; /* Actually longer, dls_cnt elements. */ > + Dl_serpath __dls_serpath_pad[1]; > + }; > +# else > Dl_serpath dls_serpath[1]; /* Actually longer, dls_cnt elements. */ > +# endif > } Dl_serinfo; > #endif /* __USE_GNU */ > Ping? Thanks, Florian
That looks OK to me, thanks. (Sorry, I thought I had already said "LGTM".)
diff --git a/dlfcn/dlfcn.h b/dlfcn/dlfcn.h index 896ad6fc9b..c550371999 100644 --- a/dlfcn/dlfcn.h +++ b/dlfcn/dlfcn.h @@ -180,7 +180,19 @@ typedef struct { size_t dls_size; /* Size in bytes of the whole buffer. */ unsigned int dls_cnt; /* Number of elements in `dls_serpath'. */ +# if __GNUC_PREREQ (3, 0) + /* The zero-length array avoids an unwanted array subscript check by + the compiler, while the surrounding anonymous union preserves the + historic size of the type. At the time of writing, GNU C does + not support structs with flexible array members in unions. */ + __extension__ union + { + Dl_serpath dls_serpath[0]; /* Actually longer, dls_cnt elements. */ + Dl_serpath __dls_serpath_pad[1]; + }; +# else Dl_serpath dls_serpath[1]; /* Actually longer, dls_cnt elements. */ +# endif } Dl_serinfo; #endif /* __USE_GNU */