https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95755

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
     Ever confirmed|0                           |1
   Last reconfirmed|                            |2020-06-19
             Blocks|                            |88781
          Component|c                           |middle-end
             Status|UNCONFIRMED                 |NEW

--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
The sizes used to trigger the warning are based on what it can determine from
the representation of source code it sees.  In this case it's the IL below
(seen in the output of -fdump-tree-strlen):

mz_format (struct mz_cb * rcb)
{
  struct mz_unity ncred;
  struct mz_unity * ocred;
  char[513] * _1;

  <bb 2> [local count: 1073741824]:
  ocred_4 = rcb_3(D)->mz_creds;
  ncred = *ocred_4;
  _1 = &rcb_3(D)->mz_url;
  snprintf (_1, 513, "%s/name/%s/abc1234", &MEM <char[129]> [(void *)&ncred +
8B], &MEM <char[161]> [(void *)&ncred + 288B]);
  ncred ={v} {CLOBBER};
  return;

}

>From the argument to the first %s directive (&MEM <char[129]> [(void *)&ncred +
8B]), rather than using its type which is unfortunately unreliable in other
contexts, the warning conservatively uses the size of the whole object, which
it calculates to be 4552 bytes.  It uses the same conservative heuristic as
optimizations use here, which could be argued is both good and bad.  It's good
in that it reflects what would happen if only the last ncred array member was a
nul-terminated string (GCC assumes that strlen results are bounded by the size
of the complete object the argument points to).  The words "may be truncated"
in the warning are used specifically to reflect that truncation is possible but
not inevitable.  It's bad because it triggers what for correct code seems like
false positives.

In this case, to avoid triggering, the warning could consider the MEM_REF type
instead (which is char[129]).  Unfortunately, because the type is seen as
unreliable and relying on it has led to bugs in the past, there's a lot of
sensitivity to using it for anything.  Alternatively, the warning could use the
offset to find the member and the size of the member (like -Wrestrict already
does).  That in this case is rcred->variant.variant01.am_field0, the first
member of the union, not the second member, az_field11, referenced in the
source.  Because they happen to have the same size the strategy would work here
but not in other cases when the first member were bigger.  Another alternative
(for unions) is to find the smallest member at the offset.  That would lead to
false negatives if the member actually referenced in the source were the bigger
one.  Yet another option is to give up if the member can't be unambiguously
identified.  That would lead to even more false negatives (basically, any
representation involving a MEM_REF would have to be excluded from the
analysis).  Yet another possibility that we have been discussing recently is
capturing the member referenced in the source earlier on, before it has been
lost to MEM_REF, and using it.  That's probably the only viable alternative but
it requires a change to the internal representation GCC uses, so it's not going
to be a simple solution.  I realize as a user you probably don't care about any
of this.  I summarize it mainly for other GCC developers.

Until we have decided on and implemented a strategy for this there are a few
ways to avoid the warning:

1) use precision to limit the amount of output of each %s directive
2) assert before the call that the lengths of the strings passed to the %s
directives aren't too long (e.g., if (strlen
(cred->variant.variant02.az_field11) > 32) __builtin_unreachable ();)
3) test the result of the call and handle the truncation somehow (e.g.,
similarly to the precondition above except with an abort or trap replacing
__builtin_unreachable if the snprintf call isn't followed by another statement)


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88781
[Bug 88781] [meta-bug] bogus/missing -Wstringop-truncation warnings

Reply via email to