[PATCH] detect null sprintf pointers (PR 78519)

Jeff Law law@redhat.com
Mon Dec 5 18:21:00 GMT 2016


On 12/04/2016 04:55 PM, Martin Sebor wrote:
> Bug 78519 points out that while the -Wformat warning flags a small
> subset of sprintf calls with a null pointer argument to a %s directive
> (those where the pointer is a constant) it misses the much bigger
> set where the pointer is not a constant but instead is determined
> to be null as a result of optimization.  This is because -Wformat
> runs too early, before any of the optimization passes that make it
> possible to detect that non-constant pointers are null.
>
> With the -Wformat-length warning running much later than -Wformat,
> it's trivial to detect and diagnose these types of bugs with it.
> The attached patch adds this warning, along with the ability to
> detect a null destination pointer when it's required to be non-null
> (this is in all of the {v,}sprintf functions and in {v,}snprintf
> when the size argument is not zero).
>
> Ultimately, the destination pointer argument (but not the format
> string) to the {v,}sprintf functions needs to be declared nonnull
> (pursuant to bug 78673) and the null-checking moved elsewhere.
> I'm testing a follow-on patch that does just that but I post this
> fix in the meantime since its main focus is the null %s argument.
>
> Martin
>
>
> gcc-78519.diff
>
>
> PR middle-end/78519 - missing warning for sprintf %s with null pointer
>
> gcc/ChangeLog:
>
> 	PR middle-end/78519
> 	* gimple-ssa-sprintf.c (format_string): Handle null pointers.
> 	(format_directive): Diagnose null pointer arguments.
> 	(pass_sprintf_length::handle_gimple_call): Diagnose null destination
> 	pointers.  Correct location of null format string in diagnostics.
>
> gcc/testsuite/ChangeLog:
>
> 	PR middle-end/78519
> 	* gcc.dg/tree-ssa/builtin-sprintf-warn-7.c: New test.
>
> diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
> index e86c4dc..7004f09 100644
> --- a/gcc/gimple-ssa-sprintf.c
> +++ b/gcc/gimple-ssa-sprintf.c
> @@ -433,7 +433,7 @@ struct result_range
>  struct fmtresult
>  {
>    fmtresult ()
> -  : argmin (), argmax (), knownrange (), bounded (), constant ()
> +  : argmin (), argmax (), knownrange (), bounded (), constant (), nullp ()
>    {
>      range.min = range.max = HOST_WIDE_INT_MAX;
>    }
> @@ -461,6 +461,9 @@ struct fmtresult
>       are also constant (such as determined by constant propagation,
>       though not value range propagation).  */
>    bool constant;
> +
> +  /* True when the argument is a null pointer.  */
> +  bool nullp;
>  };
>
>  /* Description of a conversion specification.  */
> @@ -1624,6 +1627,20 @@ format_string (const conversion_spec &spec, tree arg)
>  	      res.range.min = 0;
>  	    }
>  	}
> +      else if (arg && integer_zerop (arg))
> +	{
> +	  /* Handle null pointer argument.  */
> +
> +	  fmtresult res;
> +	  /* Set the range based on Glibc "(null)" output but leave
> +	     all other members at default to indicate that the range
> +	     isn't trustworthy.  This allows the rest of the format
> +	     string to be checked for problems.  */
By not trustworthy, I guess you mean it's only used to issue "may be" 
style warnings, right?  What benefit do you gain by encoding the 
glib-ism vs using HOST_WIDE_INT_MAX?  Presumably once you use 
HOST_WIDE_INT_MAX nothing else is going to be checked?

Jeff




More information about the Gcc-patches mailing list