diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-11-29 15:11:46 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-11-29 15:11:46 -0500 |
| commit | 75b7ee2a08aefbdb2e2202718326fadd96ee0ef0 (patch) | |
| tree | c5376b68b658398399c47d20a37b6acebaf1807f | |
| parent | bb2f890fd470fff3e42698710b56c68164491d85 (diff) | |
Fix for undefined behavior on structs/enums with paddingv2025-11-29.2
| -rw-r--r-- | CHANGES.md | 6 | ||||
| -rw-r--r-- | src/types.c | 14 |
2 files changed, 18 insertions, 2 deletions
@@ -1,5 +1,11 @@ # Version History +## v2025-11-29.2 + +### Bugfixes + +- Fix for undefined behavior on enums and structs with padding. + ## v2025-11-29 ### Syntax changes diff --git a/src/types.c b/src/types.c index 04784735..6ed24f6c 100644 --- a/src/types.c +++ b/src/types.c @@ -459,15 +459,25 @@ PUREFUNC bool is_packed_data(type_t *t) { || t->tag == FunctionType) { return true; } else if (t->tag == StructType) { + size_t offset = 0; for (arg_t *field = Match(t, StructType)->fields; field; field = field->next) { if (!is_packed_data(field->type)) return false; + size_t align = type_align(field->type); + if (align > 0 && offset % align != 0) return false; + offset += type_size(field->type); } - return true; + size_t overall_align = type_align(t); + return overall_align == 0 || (offset % overall_align == 0); } else if (t->tag == EnumType) { + size_t offset = sizeof(int32_t); for (tag_t *tag = Match(t, EnumType)->tags; tag; tag = tag->next) { if (!is_packed_data(tag->type)) return false; + size_t align = type_align(tag->type); + if (align > 0 && offset % align != 0) return false; + offset += type_size(tag->type); } - return true; + size_t overall_align = type_align(t); + return overall_align == 0 || (offset % overall_align == 0); } else { return false; } |
