On Sun, Apr 09, 2017 at 05:06:58PM -0600, Martin Sebor wrote: > PR middle-end/80364 - sanitizer detects signed integer overflow in > gimple-ssa-sprintf.c > > gcc/ChangeLog: > > PR middle-end/80364 > * gimple-ssa-sprintf.c (get_int_range): Use the specified type when > recursing, not that of the argument. > > gcc/testsuite/ChangeLog: > > PR middle-end/80364 > * gcc.dg/tree-ssa/builtin-sprintf-warn-16.c: New test. > > diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c > index 2474391..fbcf5c7 100644 > --- a/gcc/gimple-ssa-sprintf.c > +++ b/gcc/gimple-ssa-sprintf.c > @@ -961,10 +961,10 @@ get_int_range (tree arg, tree type, HOST_WIDE_INT > *pmin, HOST_WIDE_INT *pmax, > /* True if the argument's range cannot be determined. */ > bool unknown = true; > > - type = TREE_TYPE (arg); > + tree argtype = TREE_TYPE (arg); > > if (TREE_CODE (arg) == SSA_NAME > - && TREE_CODE (type) == INTEGER_TYPE) > + && TREE_CODE (argtype) == INTEGER_TYPE) > { > /* Try to determine the range of values of the integer argument. */ > wide_int min, max;
I see that as a step in the right direction, but it doesn't seem to be complete fix. > @@ -972,11 +972,11 @@ get_int_range (tree arg, tree type, HOST_WIDE_INT > *pmin, HOST_WIDE_INT *pmax, > if (range_type == VR_RANGE) > { > HOST_WIDE_INT type_min > - = (TYPE_UNSIGNED (type) > - ? tree_to_uhwi (TYPE_MIN_VALUE (type)) > - : tree_to_shwi (TYPE_MIN_VALUE (type))); > + = (TYPE_UNSIGNED (argtype) > + ? tree_to_uhwi (TYPE_MIN_VALUE (argtype)) > + : tree_to_shwi (TYPE_MIN_VALUE (argtype))); > > - HOST_WIDE_INT type_max = tree_to_uhwi (TYPE_MAX_VALUE (type)); > + HOST_WIDE_INT type_max = tree_to_uhwi (TYPE_MAX_VALUE (argtype)); For the start, consider what happens if argtype is __int128_t or __uint128_t or unsigned int here. For the first two, those tree_to_uhwi or tree_to_shwi will just ICE above (if you have VR_RANGE for those, shouldn't be hard to write testcase). So likely you need to ignore range info for invalid args with precision greater than that of integer_type_node (i.e. INT_TYPE_SIZE). unsigned int is I think not UB when passed to var-args and read as int, it is just implementation defined how is it converted into int (I could be wrong). In that case (i.e. TYPE_UNSIGNED and precision equal to INT_TYPE_SIZE) I think you need to either handle it like you do only if the max is smaller or equal than INT_MAX and punt to full int range otherwise, or need to take the unsigned -> int conversion into account. I think passing unsigned int arg bigger than __INT_MAX__ is not well defined, because that means negative precision in the end. And, if you never change type, so type == integer_type_node, you might consider not passing that argument at all, the behavior is hardcoded for that type anyway (assumption that it fits into shwi or uhwi etc.). Perhaps in addition to the type_min/type_max check you do to determine knownrange follow it by similar range check for integer_type_node range and don't set unknown to false if it is not within integer_type_node range? The TYPE_PRECISION <= INT_TYPE_SIZE check will be still needed not to trigger the ICEs. Jakub