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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |diagnostic
             Status|UNCONFIRMED                 |ASSIGNED
   Last reconfirmed|                            |2017-03-16
           Assignee|unassigned at gcc dot gnu.org      |msebor at gcc dot 
gnu.org
   Target Milestone|---                         |8.0
     Ever confirmed|0                           |1

--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
The root cause is that the maybe_emit_sprintf_chk_warning function in
builtins.c uses c_strlen() to compute the length of the string argument to the
"%s" directive.  The function should instead leave the length computation to
the check_sizes() function which has the smarts to figure out the (minimum)
length even from a non-literal argument.

The following untested patch makes this change and allows the test case to be
diagnosed.

@ -9734,33 +9793,26 @@ maybe_emit_sprintf_chk_warning (tree exp, enum
built_in_function fcode)
   if (!init_target_chars ())
     return;

+  tree arg;
   /* If the format doesn't contain % args or %%, we know its size.  */
   if (strchr (fmt_str, target_percent) == 0)
-    len = build_int_cstu (size_type_node, strlen (fmt_str));
+    arg = build_int_cstu (size_type_node, strlen (fmt_str));
   /* If the format is "%s" and first ... argument is a string literal,
      we know it too.  */
   else if (fcode == BUILT_IN_SPRINTF_CHK
           && strcmp (fmt_str, target_percent_s) == 0)
     {
-      tree arg;
-
       if (nargs < 5)
        return;
       arg = CALL_EXPR_ARG (exp, 4);
       if (! POINTER_TYPE_P (TREE_TYPE (arg)))
        return;
-
-      len = c_strlen (arg, 1);
-      if (!len || ! tree_fits_uhwi_p (len))
-       return;
     }
   else
     return;

-  /* Add one for the terminating nul.  */
-  len = fold_build2 (PLUS_EXPR, TREE_TYPE (len), len, size_one_node);
   check_sizes (OPT_Wstringop_overflow_,
-              exp, /*size=*/NULL_TREE, /*maxlen=*/NULL_TREE, len, size);
+              exp, /*size=*/NULL_TREE, /*maxlen=*/NULL_TREE, arg, size);
 }

 /* Emit warning if a free is called with address of a variable.  */

Reply via email to