https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110603
Aldy Hernandez <aldyh at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |amacleod at redhat dot com
--- Comment #4 from Aldy Hernandez <aldyh at gcc dot gnu.org> ---
(In reply to wierton from comment #0)
> The testing program:
> ```
> typedef long unsigned int size_t;
> void *memcpy(void *, const void *, size_t);
> int snprintf(char *restrict, size_t, const char *restrict, ...);
>
> extern char a[2];
> void test_func_on_line_62(void) {
> memcpy(a, "12", sizeof("12") - 1);
> const int res = snprintf(0, 0, "%s", a);
> if (res <= 3)
> do {
> extern void f(void);
> f();
> } while (0);
> }
The sprintf pass is ICEing because it's trying to build a nonsensical range of
[2,1]. Legacy irange tried harder with swapped ranges, but in the above case
it would actually drop to VARYING:
- /* There's one corner case, if we had [C+1, C] before we now have
- that again. But this represents an empty value range, so drop
- to varying in this case. */
Which would cause the sprintf pass to set a global range of VARYING. I can't
remember whether this meant nuking the known global range, or ignoring it
altogether (the semantics changed in the last release or two). My guess is the
later, since set_range_info() improves ranges, never pessimizes them.
Now the reason we're passing swapped endpoints seems to originate in
get_range_strlen_dynamic(). It is setting a min of 2, courtesy of the nonzero
characters in the memcpy:
memcpy(a, "12", sizeof("12") - 1);
This comes from tree-ssa-strlen.c:
if (!pdata->minlen && si->nonzero_chars)
{
if (TREE_CODE (si->nonzero_chars) == INTEGER_CST)
pdata->minlen = si->nonzero_chars;
Further down we set a max of 1, stemming from the size of a[2] minus 1 for the
terminating null:
if (TREE_CODE (size) == INTEGER_CST)
{
++off; /* Increment for the terminating nul. */
tree toffset = build_int_cst (size_type_node, off);
pdata->maxlen = fold_build2 (MINUS_EXPR, size_type_node,
size,
toffset);
pdata->maxbound = pdata->maxlen;
}
I don't understand this code enough to opine, but at the worst we could bail if
the ends are swapped. It's no worse than what we had before.