[vlc-devel] [PATCH] objects: ensure accessing payload parents via container_of is correct

Steve Lhomme robux4 at gmail.com
Wed Jul 26 10:04:54 CEST 2017


As a side note, the standard has this example:
***
struct s { int n; double d[]; };

struct s t1 = { 0 };          // valid
struct s t2 = { 1, { 4.2 }};  // invalid
t1.n = 4;                     // valid
t1.d[0] = 4.2;                // might be undefined behavior

The initialization of t2 is invalid (and violates a constraint)
because struct s is treated as if it did not contain member d. The
assignment to t1.d[0] is probably undefined behavior, but it is
possible that

sizeof (struct s) >= offsetof(struct s, d) + sizeof (double)

in which case the assignment would be legitimate. Nevertheless, it
cannot appear in strictly conforming code.
***

So it seems possible, according to the standard, that sizeof(struct s)
and offsetof(struct s, d) do not have the same value.

On Wed, Jul 26, 2017 at 9:39 AM, Steve Lhomme <robux4 at videolabs.io> wrote:
> In those cases the parent of a payload is accessed via the container_of() macro
> that removes the size of the containing structure of the payload pointer. This
> size comes from offsetof() the flexible array element at the end of the parent
> structure.
> The compiler is supposed to treat the flexible array element has having no size
> in the structure (except when accessed).
> ---
>  src/misc/objects.c | 3 +++
>  src/misc/objres.c  | 2 ++
>  2 files changed, 5 insertions(+)
>
> diff --git a/src/misc/objects.c b/src/misc/objects.c
> index 91eebdaf20..e953e38a64 100644
> --- a/src/misc/objects.c
> +++ b/src/misc/objects.c
> @@ -186,6 +186,9 @@ void *vlc_custom_create (vlc_object_t *parent, size_t length,
>       * and zeroes the rest.
>       */
>      assert (length >= sizeof (vlc_object_t));
> +    static_assert( sizeof(vlc_object_internals_t) ==
> +                   offsetof(vlc_object_internals_t, aligned_end),
> +                  "flexible array size is not ignored" );
>
>      vlc_object_internals_t *priv = malloc (sizeof (*priv) + length);
>      if (unlikely(priv == NULL))
> diff --git a/src/misc/objres.c b/src/misc/objres.c
> index 1afaccb700..b9aa87f30d 100644
> --- a/src/misc/objres.c
> +++ b/src/misc/objres.c
> @@ -51,6 +51,8 @@ void *vlc_objres_new(size_t size, void (*release)(void *))
>          errno = ENOMEM;
>          return NULL;
>      }
> +    static_assert( sizeof(struct vlc_res) == offsetof(struct vlc_res, payload),
> +                   "flexible array size is not ignored" );
>
>      struct vlc_res *res = malloc(sizeof (*res) + size);
>      if (unlikely(res == NULL))
> --
> 2.12.1
>


More information about the vlc-devel mailing list