On Wed, Feb 05, 2025 at 12:59:58PM +0100, Jakub Jelinek wrote:
> Hi!
>
> Kees, any progress on this?
Hi!
I need to take another run at it. I got stalled out when I discovered
that I array-of-char-arrays attributes got applied at the "wrong" depth,
and stuff wasn't working.
e.g.:
char acpi_table[TABLE_SIZE][4] __attribute((nonstring)) = {
{ "ohai" },
{ "1234" },
};
when nonstring was checked for on something like "acpi_table[2]" it
wouldn't be found, since it was applied at the top level.
>
> On Mon, Jan 06, 2025 at 04:34:27PM -0500, Marek Polacek wrote:
> > > - pedwarn_init (init_loc, 0,
> > > - ("initializer-string for array of %qT "
> > > - "is too long"), typ1);
> > > - else if (warn_unterminated_string_initialization
> > > - && compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0)
> > > - warning_at (init_loc, OPT_Wunterminated_string_initialization,
> > > - ("initializer-string for array of %qT "
> > > - "is too long"), typ1);
> > > +
> > > if (compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0)
> > > {
> > > - unsigned HOST_WIDE_INT size
> > > - = tree_to_uhwi (TYPE_SIZE_UNIT (type));
> > > - const char *p = TREE_STRING_POINTER (inside_init);
> > > -
> > > - inside_init = build_string (size, p);
> > > + unsigned HOST_WIDE_INT avail
> > > + = tree_to_uhwi (TYPE_SIZE_UNIT (type));
> > > + unsigned unit = TYPE_PRECISION (typ1) / BITS_PER_UNIT;
> > > + const char *p = TREE_STRING_POINTER (inside_init);
> > > +
> > > + /* Construct truncated string. */
> > > + inside_init = build_string (avail, p);
> > > +
> > > + /* Subtract the size of a single (possibly wide) character
> > > + because it may be ok to ignore the terminating NUL char
> > > + that is counted in the length of the constant. */
> > > + if (warn_cxx_compat || len - unit > avail)
> > > + {
> > > + pedwarn_init (init_loc, 0,
> > > + ("initializer-string for array of %qT "
> > > + "is too long (%lu chars into %lu "
> > > + "available)"), typ1, len, avail);
> > > + }
> >
> > No need for the { } here.
>
> The indentation is wrong in the whole block.
> The { after compare_tree_int is indented by 2 tabs (so 16 columns), but
> unsigned HOST_WIDE_INT avail already by 2 tabs and 3 spaces rather than
> 2 tabs and 2 spaces. So it is one column more right than it should be.
>
> Anyway, more importantly, the "warn_cxx_compat || " part looks wrong.
> For -Wc++-compat we should (perhaps with slightly different wording)
> preserve the GCC 14 behavior, which was
> /* Subtract the size of a single (possibly wide) character
> because it's ok to ignore the terminating null char
> that is counted in the length of the constant. */
> if (compare_tree_int (TYPE_SIZE_UNIT (type), len - unit) < 0)
> pedwarn_init (init_loc, 0,
> ("initializer-string for array of %qT "
> "is too long"), typ1);
> else if (warn_cxx_compat
> && compare_tree_int (TYPE_SIZE_UNIT (type), len) < 0)
> warning_at (init_loc, OPT_Wc___compat,
> ("initializer-string for array of %qT "
> "is too long for C++"), typ1);
> So, if (len - unit > avail) do the pedwarn_init (also note that %lu is
> wrong for unsigned HOST_WIDE_INT, one should use %wu instead; or for the
> avail case one could just print %E and pass it TYPE_SIZE_UNIT (type);
> unsigned HOST_WIDE_INT doesn't have to be unsigned long, it can be also
> unsigned long long). And if warn_cxx_compat, do warning_at, IMNSHO
> with OPT_Wc___compat, with the "is too long for C++" substring in it
> and perhaps some more details (len and avail too).
>
> Though, perhaps we should also change
> C ObjC Var(warn_unterminated_string_initialization) Warning LangEnabledBy(C
> ObjC,Wextra || Wc++-compat)
> to
> C ObjC Var(warn_unterminated_string_initialization) Warning LangEnabledBy(C
> ObjC,Wextra)
> and adjust documentation, because say
> -Wno-unterminated-string-initialization will no longer turn off that
> warning, essentially -Wc++-compat and -Wunterminated-string-initialization
> are then independent warnings with -Wc++-compat having priority over the
> latter.
> Or we could guard it with
> warn_cxx_compat && warn_unterminated_string_initialization
> but then the question is what to pass to second warning_at option,
> because one needs both.
> So, I think it is better to keep -Wc++-compat working as before (perhaps
> with the extra descriptions of the two lengths) and then have this new
> -Wunterminated-string-initialization warning implied by -Wextra which
> does nothing in the rare case when -Wc++-compat is on, and otherwise
> does the new stuff of warning except when initializing nonstring
> objects.
Okay, I will take a stab at getting this reorganized. Thanks for the
review!
--
Kees Cook