[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 --- Comment #14 from joseph at codesourcery dot com --- That wording is long including several examples. You can see it in http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf subclause 6.7.2.1 (C99 + TC1 + TC2 + TC3).
[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 Eric Gallager changed: What|Removed |Added CC||joseph at codesourcery dot com, ||pinskia at gcc dot gnu.org, ||rguenth at gcc dot gnu.org --- Comment #13 from Eric Gallager --- (In reply to jos...@codesourcery.com from comment #10) > On Thu, 25 Jun 2015, P at draigBrady dot com wrote: > > > I'm not understanding completely TBH. Are flexible array members not > > special? > > Should the optimizations be restricted on access through the flexible array, > > because I presume most/all existing allocation code is not considering this > > alignment/padding issue. I certainly didn't notice any examples when looking > > into a workaround which I came up with independently. For my reference there > > are some notes RE GCC's divergence from C99 re padding and flexi arrays at: > > https://sites.google.com/site/embeddedmonologue/home/c-programming/data-alig > > That page doesn't exist - I assume you mean: > https://sites.google.com/site/embeddedmonologue/home/c-programming/data- > alignment-structure-padding-and-flexible-array-member > > That page is over ten years out of date - it's quoting the wording in C99 > as it was before it was corrected by TC2 (published 2004-11-15). You > should look at the post-TC2 wording rather than the old wording with > various defects in it. Could you quote the post-TC2 wording here for us so we don't have to go looking?
[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 Florian Weimer changed: What|Removed |Added Status|RESOLVED|UNCONFIRMED Resolution|INVALID |--- --- Comment #12 from Florian Weimer --- Here's a new test case. It prints for me (without Address Sanitizer): count 2, align 4, minimum size 10, struct size 12, actual size 12 count 5, align 4, minimum size 13, struct size 16, actual size 20 count 0, align 8, minimum size 8, struct size 8, actual size 8 count 3, align 4, minimum size 11, struct size 12, actual size 24 * count 0, align 16, minimum size 8, struct size 16, actual size 8 count 8, align 4, minimum size 16, struct size 16, actual size 16 count 4, align 4, minimum size 12, struct size 12, actual size 12 count 2, align 4, minimum size 10, struct size 12, actual size 12 * count 2, align 8, minimum size 10, struct size 16, actual size 12 count 6, align 4, minimum size 14, struct size 16, actual size 16 count 7, align 4, minimum size 15, struct size 16, actual size 16 count 3, align 4, minimum size 11, struct size 12, actual size 12 count 3, align 4, minimum size 11, struct size 12, actual size 12 count 6, align 4, minimum size 14, struct size 16, actual size 44 * count 5, align 32, minimum size 13, struct size 32, actual size 16 count 8, align 4, minimum size 16, struct size 16, actual size 16 count 9, align 4, minimum size 17, struct size 20, actual size 20 count 7, align 4, minimum size 15, struct size 16, actual size 16 count 1, align 4, minimum size 9, struct size 12, actual size 12 * count 1, align 8, minimum size 9, struct size 16, actual size 12 I believe this shows that GCC has some bug in this area. Whether it's the over-reads (but over-reads can be fine here because they cannot trap, and GCC knows that they won't introduce observable data races), the object allocation in the .data section (again, could be harmless), or the Address Sanitizer report, I'm not sure. #include #include #include #include struct flexible { int count; int align; char bytes[]; }; #define ARGS_0 #define ARGS_1 1 #define ARGS_2 1, 2 #define ARGS_3 1, 2, 3 #define ARGS_4 1, 2, 3, 4 #define ARGS_5 1, 2, 3, 4, 5 #define ARGS_6 1, 2, 3, 4, 5, 6 #define ARGS_7 1, 2, 3, 4, 5, 6, 7 #define ARGS_8 1, 2, 3, 4, 5, 6, 7, 8 #define ARGS_9 1, 2, 3, 4, 5, 6, 7, 8, 9 #define DECL(name, count, align) \ _Alignas (align) struct flexible name = {count, align,{ ARGS_##count }} DECL (v4, 4, 4); DECL (v1, 1, 8); DECL (v7, 1, 4); DECL (v17, 7, 4); DECL (v15, 9, 4); DECL (v16, 8, 4); DECL (v11, 5, 32); DECL (v12, 6, 4); DECL (v5, 3, 4); DECL (v9, 3, 4); DECL (v13, 7, 4); DECL (v18, 6, 4); DECL (v2, 2, 8); DECL (v8, 2, 4); DECL (v10, 4, 4); DECL (v14, 8, 4); DECL (v0, 0, 16); DECL (v3, 3, 4); DECL (v5a, 0, 8); DECL (v19, 5, 4); DECL (v6, 2, 4); enum { count = 21 }; static int cmp(const void *a, const void *b) { struct flexible *const *a1 = a; struct flexible *const *b1 = b; if (*a1 < *b1) return -1; if (*a1 > *b1) return 1; return 0; } int main() { struct flexible *p[count] = {, , , , , , , , , , , , , , , , , , , , }; qsort (p, count, sizeof (p[0]), cmp); for (int i = 0; i < count - 1; ++i) { size_t min_size = offsetof (struct flexible, bytes) + p[i]->count; size_t align_mask = p[i]->align - 1; /* Struct size is the size that a struct with the requested length of the flexible array member would have. */ size_t struct_size = (min_size + align_mask) & ~align_mask; /* The actual size is the offset between this and the next object in the data section. (This can be an over-estimate if other objects not listed above are placed between the listed objects.) */ size_t actual_size = (p[i + 1] - p[i]) * sizeof (*p[i]); /* The lines marked with * have an object whose struct size exceeds the object size. If GCC assumes that objects always have their struct size allocated, this leads to an out-of-bounds acccess. */ printf ("%c count %d, align %d, minimum size %zu, struct size %zu, actual size %zu\n", struct_size > actual_size ? '*' : ' ', p[i]->count, p[i]->align, min_size, struct_size, actual_size); } }
[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 Florian Weimer changed: What|Removed |Added CC||fw at gcc dot gnu.org --- Comment #11 from Florian Weimer --- I think this is a GCC bug. Object sizes do not have to be a multiple of the object alignment. Consider this example: #include #include #include _Alignas (128) unsigned v0 = 128; _Alignas (8) unsigned v1 = 8; _Alignas (8) unsigned v2 = 8; _Alignas (8) unsigned v3 = 8; _Alignas (4) unsigned v4 = 4; _Alignas (4) unsigned v5 = 4; _Alignas (8) unsigned v6 = 8; _Alignas (8) unsigned v7 = 8; _Alignas (8) unsigned v8 = 8; _Alignas (4) unsigned v9 = 4; _Alignas (4) unsigned v10 = 4; static int cmp(const void *a, const void *b) { unsigned *const *a1 = a; unsigned *const *b1 = b; if (*a1 < *b1) return -1; if (*a1 > *b1) return 1; return 0; } int main() { unsigned *p[] = {, , , , , , , , , }; qsort (p, 10, sizeof (p[0]), cmp); for (int i = 0; i < 9; ++i) { printf ("%d: alignment %u, size %zd\n", i, *p[i], (p[i + 1] - p[i]) * sizeof (*p[i])); } } With gcc-5.3.1-6.fc23.x86_64, it prints this for me: 0: alignment 4, size 4 1: alignment 4, size 4 2: alignment 8, size 8 3: alignment 8, size 8 4: alignment 8, size 4 5: alignment 4, size 4 6: alignment 4, size 8 7: alignment 8, size 8 8: alignment 8, size 8 So the assumption that objects are at least as large as their alignment appears to be refuted by code generated by GCC.
[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 --- Comment #9 from Pádraig Brady P at draigBrady dot com --- I'm not understanding completely TBH. Are flexible array members not special? Should the optimizations be restricted on access through the flexible array, because I presume most/all existing allocation code is not considering this alignment/padding issue. I certainly didn't notice any examples when looking into a workaround which I came up with independently. For my reference there are some notes RE GCC's divergence from C99 re padding and flexi arrays at: https://sites.google.com/site/embeddedmonologue/home/c-programming/data-alig
[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 --- Comment #10 from joseph at codesourcery dot com joseph at codesourcery dot com --- On Thu, 25 Jun 2015, P at draigBrady dot com wrote: I'm not understanding completely TBH. Are flexible array members not special? Should the optimizations be restricted on access through the flexible array, because I presume most/all existing allocation code is not considering this alignment/padding issue. I certainly didn't notice any examples when looking into a workaround which I came up with independently. For my reference there are some notes RE GCC's divergence from C99 re padding and flexi arrays at: https://sites.google.com/site/embeddedmonologue/home/c-programming/data-alig That page doesn't exist - I assume you mean: https://sites.google.com/site/embeddedmonologue/home/c-programming/data-alignment-structure-padding-and-flexible-array-member That page is over ten years out of date - it's quoting the wording in C99 as it was before it was corrected by TC2 (published 2004-11-15). You should look at the post-TC2 wording rather than the old wording with various defects in it.
[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 Richard Biener rguenth at gcc dot gnu.org changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #8 from Richard Biener rguenth at gcc dot gnu.org --- Yes, consider struct X { int n; char x[1]; }; which has sizeof(X) == 8 unless you use __attribute__((packed)) (in which case alignment also gets dropped down to 1).
[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 --- Comment #4 from Pádraig Brady P at draigBrady dot com --- I should note that I worked around the issue by increasing the allocation for the structure on the heap up to a multiple of alignof(the_struct). See: http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=commitdiff;h=49078a78
[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 --- Comment #7 from Pádraig Brady P at draigBrady dot com --- Created attachment 35852 -- https://gcc.gnu.org/bugzilla/attachment.cgi?id=35852action=edit reproducer
[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 Andrew Pinski pinskia at gcc dot gnu.org changed: What|Removed |Added Status|RESOLVED|UNCONFIRMED Resolution|INVALID |--- --- Comment #6 from Andrew Pinski pinskia at gcc dot gnu.org --- More to the point this might actually be a -fsanitize=address bug so reopening for that issue. By the way we know the alignment of the struct is 4 which means loading a 4 byte would be valid.
[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 --- Comment #3 from Pádraig Brady P at draigBrady dot com --- Created attachment 35851 -- https://gcc.gnu.org/bugzilla/attachment.cgi?id=35851action=edit disassembly of forced good mem access
[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 --- Comment #2 from Pádraig Brady P at draigBrady dot com --- Created attachment 35850 -- https://gcc.gnu.org/bugzilla/attachment.cgi?id=35850action=edit disassembly of problematic mem access
[Bug middle-end/66661] incorrect memory access in optimization with flexible array member
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=1 Andrew Pinski pinskia at gcc dot gnu.org changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #5 from Andrew Pinski pinskia at gcc dot gnu.org --- (In reply to Pádraig Brady from comment #4) I should note that I worked around the issue by increasing the allocation for the structure on the heap up to a multiple of alignof(the_struct). See: http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=commitdiff;h=49078a78 That is not just a workaround but a correct patch. The size of the memory allocated needs to be a multiply of the alignment of the struct to be valid. The reason why it works for you with your reduced testcase is because the alignment of the struct is 1.