Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@withinboredom
Copy link
Member

@withinboredom withinboredom commented Nov 15, 2025

The zend_ast_attr type was defined as uint16_t, limiting it to 16 bits, but it’s used to store ZEND_ACC_* flags which can use bits up to 31:

  • ZEND_ACC_OVERRIDE = (1 << 28)
  • ZEND_ACC_ENUM = (1 << 28)
  • ZEND_ACC_STRICT_TYPES = (1U << 31)

While the current code doesn’t appear to assign these high-bit flags to ast->attr fields, the type mismatch creates a potential bug where any future code attempting to store ZEND_ACC flags with bits 16–31 would have those bits silently truncated to zero.

Additionally, several functions (zend_ast_create_va, zend_ast_create_ex_*, etc.) accept uint32_t or zend_ast_attr parameters before assigning to the attr field, creating a truncation point at line 821 in zend_language_parser.y where zend_modifier_list_to_flags() returns uint32_t.

This change:

  1. Changes zend_ast_kind typedef from uint16_t to uint32_t
  2. Changes zend_ast_attr typedef from uint16_t to uint32_t

Extending kind to uint32_t maintains natural alignment without requiring explicit padding fields. The structure sizes remain unchanged. Padding was already present implicitly due to alignment.

Copy link
Member

@ndossche ndossche left a comment

Choose a reason for hiding this comment

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

Don't add these padding fields. You could just extend the kind to 32-bits as well if you want to make it more explicit.

@iluuu1994
Copy link
Member

Is this really worthwhile? We can probably shuffle around the flags to make it fit in the 16 bit field if necessary. We also basically just ran out of 32 bit flags anyway, so some shuffling is necessary regardless.

The zend_ast_attr type was defined as uint16_t, limiting it to 16 bits,
but it's used to store ZEND_ACC_* flags which can use bits up to 31:

- ZEND_ACC_OVERRIDE = (1 << 28)
- ZEND_ACC_ENUM = (1 << 28)
- ZEND_ACC_STRICT_TYPES = (1U << 31)

While current code doesn't appear to assign these high-bit flags to
ast->attr fields, the type mismatch creates a potential bug where any
future code attempting to store ZEND_ACC flags with bits 16-31 would
have those bits silently truncated to zero.

Additionally, several functions (zend_ast_create_va, zend_ast_create_ex_*,
etc.) accept uint32_t or zend_ast_attr parameters before assigning to the
attr field, creating a truncation point at line 821 in zend_language_parser.y
where zend_modifier_list_to_flags() returns uint32_t.

This change:
1. Changes zend_ast_kind typedef from uint16_t to uint32_t
2. Changes zend_ast_attr typedef from uint16_t to uint32_t

Extending kind to uint32_t maintains natural alignment without requiring
explicit padding fields. The structure sizes remain unchanged. Padding
was already present implicitly due to alignment.
@withinboredom
Copy link
Member Author

Is this really worthwhile? We can probably shuffle around the flags to make it fit in the 16-bit field if necessary.

An alternative would be to change zend_ast_create_zval_int, zend_ast_create_va, etc. to take a 16-bit attribute, so it would be more clear that it won’t silently truncate a 32-bit value. But that would then require a cast, which would cause an overflow instead of a truncation, which is probably worse.

The goal here isn’t to solve the fact that flags are running out, but to make it less surprising for new contributors who wonder why adding a new flag appears to be ignored.

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.

3 participants