Skip to content

zend_portability: Add ZEND_CONTAINER_OF()#21903

Open
TimWolla wants to merge 2 commits intophp:masterfrom
TimWolla:container-of
Open

zend_portability: Add ZEND_CONTAINER_OF()#21903
TimWolla wants to merge 2 commits intophp:masterfrom
TimWolla:container-of

Conversation

@TimWolla
Copy link
Copy Markdown
Member

Changes made with Coccinelle:

@@
type T_container;
identifier member;
expression e;
@@

- (T_container *)(((char *)(e)) - offsetof(T_container, member))
+ ZEND_CONTAINER_OF(e, T_container, member)

@@
type T_container;
identifier member;
expression e;
typedef uintptr_t;
@@

- (T_container *)(((uintptr_t)(e)) - offsetof(T_container, member))
+ ZEND_CONTAINER_OF(e, T_container, member)

@@
type T_container;
identifier member;
expression e;
@@

- (const T_container *)(((char *)(e)) - offsetof(T_container, member))
+ ZEND_CONTAINER_OF(e, T_container, member)

@@
type T_container;
identifier member;
expression e;
typedef uintptr_t;
@@

- (const T_container *)(((uintptr_t)(e)) - offsetof(T_container, member))
+ ZEND_CONTAINER_OF(e, T_container, member)

Changes made with Coccinelle:

    @@
    type T_container;
    identifier member;
    expression e;
    @@

    - (T_container *)(((char *)(e)) - offsetof(T_container, member))
    + ZEND_CONTAINER_OF(e, T_container, member)

    @@
    type T_container;
    identifier member;
    expression e;
    typedef uintptr_t;
    @@

    - (T_container *)(((uintptr_t)(e)) - offsetof(T_container, member))
    + ZEND_CONTAINER_OF(e, T_container, member)

    @@
    type T_container;
    identifier member;
    expression e;
    @@

    - (const T_container *)(((char *)(e)) - offsetof(T_container, member))
    + ZEND_CONTAINER_OF(e, T_container, member)

    @@
    type T_container;
    identifier member;
    expression e;
    typedef uintptr_t;
    @@

    - (const T_container *)(((uintptr_t)(e)) - offsetof(T_container, member))
    + ZEND_CONTAINER_OF(e, T_container, member)
Comment thread Zend/zend_portability.h
#define ZEND_ELEMENT_COUNT(m)
#endif

#define ZEND_CONTAINER_OF(ptr, Type, member) ((Type*)((char*)(1 ? (ptr) : &((Type*)0)->member) - offsetof(Type, member)))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This will discard const from ptr. With _Generic it would be possible to retain it. get_bcmath_number_from_obj() looks like the only relevant case, but also looks somewhat questionable. obj should not be const if we return a mutable pointer derived from it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_bcmath_number_from_obj() simply seems to be my mistake.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_bcmath_number_from_obj() simply seems to be my mistake.

Yes, that's a pre-existing bug.

With _Generic it would be possible to retain it.

Good idea, will look into that.

@ndossche
Copy link
Copy Markdown
Member

ndossche commented May 2, 2026

I think this relies on UB (pointer arithmetic on NULL)

@TimWolla
Copy link
Copy Markdown
Member Author

TimWolla commented May 2, 2026

pointer arithmetic on NULL

That branch is never evaluated; it's also the “accepted” solution to define container_of() in a type-safe way without statement expressions. So of all possible UB, this seems to be reasonably safe.

@ndossche
Copy link
Copy Markdown
Member

ndossche commented May 2, 2026

pointer arithmetic on NULL

That branch is never evaluated

This doesn't matter for UB.

it's also the “accepted” solution to define container_of() in a type-safe way without statement expressions.

The Linux kernel is compiled with various flags that makes various UB defined, so I'm not so sure this is a valid comparison.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants