On 07/30/18 15:03, Richard Biener wrote: > On Mon, 30 Jul 2018, Bernd Edlinger wrote: > >> Hi, >> >> this is how I would like to handle the over length strings issue in the C FE. >> If the string constant is exactly the right length and ends in one explicit >> NUL character, shorten it by one character. >> >> I thought Martin would be working on it, but as this is a really simple fix, >> I would dare to send it to gcc-patches anyway, hope you don't mind... >> >> The patch is relative to the other patch here: >> https://gcc.gnu.org/ml/gcc-patches/2018-07/msg01800.html >> >> >> Bootstrapped and reg-tested on x86_64-pc-linux-gnu. >> Is it OK for trunk? > > I'll leave this to FE maintainers but can I ask you to verify the > (other) FEs do not leak this kind of invalid initializers to the > middle-end? I suggest to put this verification in > output_constructor which otherwise happily truncates initializers > with excess size. There's also gimplification which might elide > a = { "abcd", "cdse" }; to a.x = "abcd"; a.y = "cdse"; but > hopefully there the GIMPLE verifier (verify_gimple_assign_single) > verifies this - well, it only dispatches to useless_type_conversion_p > (lhs_type, rhs1_type) for this case, but non-flexarrays should be > handled fine there. >
Okay, this is what I am currently playing with. There is still a major fault in the fortran FE, but I believe sanitizing the middle-end is worth it.... IMHO sanitizing should have priority over new optimizations :( Thanks Bernd.
Index: gcc/varasm.c =================================================================== --- gcc/varasm.c (Revision 263072) +++ gcc/varasm.c (Arbeitskopie) @@ -4774,6 +4774,29 @@ initializer_constant_valid_for_bitfield_p (tree va return false; } +/* Check if a STRING_CST fits into the field. + Tolerate only the case when the NUL termination + does not fit into the field. */ + +bool +check_string_literal (tree string, unsigned HOST_WIDE_INT size) +{ + tree eltype = TREE_TYPE (TREE_TYPE (string)); + unsigned HOST_WIDE_INT elts = tree_to_uhwi (TYPE_SIZE_UNIT (eltype)); + const char *p = TREE_STRING_POINTER (string); + int len = TREE_STRING_LENGTH (string); + + if (elts != 1 && elts != 2 && elts != 4) + return false; + if (len <= 0 || len % elts != 0) + return false; + if ((unsigned)len != size && (unsigned)len != size + elts) + return false; + if (memcmp (p + len - elts, "\0\0\0\0", elts) != 0) + return false; + return true; +} + /* output_constructor outer state of relevance in recursive calls, typically for nested aggregate bitfields. */ @@ -4942,6 +4965,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT case STRING_CST: thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), size); + gcc_checking_assert (check_string_literal (exp, thissize)); assemble_string (TREE_STRING_POINTER (exp), thissize); break; case VECTOR_CST: