Jason Merrill wrote:
> On 09/16/2014 06:23 AM, Ulrich Weigand wrote:
> > Now in this case, we cast a pointer to the array to a pointer to a base
> > type of the array element type -- but the intent is for the pointer to still
> > refer to the whole array.  (Of course, this only works if the base type
> > is actually the same size as the array type.)
> 
> And I'm arguing that this intent is not well expressed by the code.  :)
> 
> If they want to refer to the whole array, why are they casting the 
> pointer to a different type?  And why are they passing the "subobject 
> only" value as the second argument?

It looks more reasonable in the original source :-)  What we have there
is a definition of struct Pollfd that wraps the standard header file type
struct pollfd and adds a couple of helpers (like constructors that set up
the struct in some standard ways etc.).  Subsequent source code simply
uses struct Pollfd wherever struct pollfd would otherwise be used.

In particular, this occurs in a call to the system "poll" routine:

  struct Pollfd myfd[10];
[...]
  poll(myfd, count, 0);  // 1 < count < 10

Now, that routine comes from glibc header files, and if _FORTIFY_SOURCE
is defined, it becomes an inline function that resolves after inlining
and constant folding in this instance to something like:

  __poll_chk ((struct pollfd *)myfd, count, 0,
              __builtin_object_size ((struct pollfd *)myfd, 1));

The __poll_chk routine then performs a runtime check that the value of
"count" is within range of the object size passed in as fourth argument.

Note that the cast is actually implicit, it simply occurs because the
parameter of the inlined "poll" function is "struct pollfd *", but the
caller passes in a "struct Pollfd *".

The "subobject only" value comes from glibc headers, where they use it
deliberately: poll is supposed to get an array of pollfd structures,
and it is OK to access those; but if that array is embedded within a
larger structure, we want to avoid overruns into the rest of the
structure.

Is this "wrapping" of system types in a derived calls supposed to work?
If there is a better way to express this without breaking glibc headers,
I'd be happy to let the authors know ...

> > Note that with a somewhat equivalent C construct:
> >
> > struct pollfd
> >    {
> >      int fd;
> >      short int events;
> >      short int revents;
> >    };
> >
> > struct Pollfd
> >    {
> >      struct pollfd x;
> >    };
> >
> > struct Pollfd myfd[10];
> >
> > we still get an object size of 80 for either:
> >
> >    __builtin_object_size ((struct pollfd *)myfd, 1);
> >
> > or even
> >
> >    __builtin_object_size (&myfd->x, 1);
> 
> That strikes me as a bug, especially the second one.

Jakub, any thoughts on this?

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  ulrich.weig...@de.ibm.com

Reply via email to