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: