Commit 1cdfb80a by Jakub Jelinek

sccvn: Avoid overflows in push_partial_def

The following patch attempts to avoid dangerous overflows in the various
push_partial_def HOST_WIDE_INT computations.
This is achieved by performing the subtraction offset2i - offseti in
the push_partial_def function and before doing that doing some tweaks.
If a constant store (non-CONSTRUCTOR) is too large (perhaps just
hypothetical case), native_encode_expr would fail for it, but we don't
necessarily need to fail right away, instead we can treat it like
non-constant store and if it is already shadowed, we can ignore it.
Otherwise, if it at most 64-byte and the caller ensured that there is
a range overlap and push_partial_def ensures the load is at most 64-byte,
I think we should be fine, offset (relative to the load)
can be from -64*8+1 to 64*8-1 only and size at most 64*8, so no risks of
overflowing HOST_WIDE_INT computations.
For CONSTRUCTOR (or non-constant) stores, those can be indeed arbitrarily
large, the caller just checks that both the absolute offset and size fit
into signed HWI.  But, we store the same bytes in that case over and over
(both in the {} case where it is all 0, and in the hypothetical future case
where we handle in push_partial_def also memset (, 123, )), so we can tweak
the write range for our purposes.  For {} store we could just cap it at the
start offset and/or offset+size because all the bits are 0, but I wrote it
in anticipation of the memset case and so the relative offset can now be
down to -7 and similarly size can grow up to 64 bytes + 14 bits, all this
trying to preserve the offset difference % BITS_PER_UNIT or end as well.

2020-03-04  Jakub Jelinek  <jakub@redhat.com>

	* tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): Add offseti
	argument.  Change pd argument so that it can be modified.  Turn
	constant non-CONSTRUCTOR store into non-constant if it is too large.
	Adjust offset and size of CONSTRUCTOR or non-constant store to avoid
	overflows.
	(vn_walk_cb_data::vn_walk_cb_data, vn_reference_lookup_3): Adjust
	callers.
parent dca54007
2020-03-04 Jakub Jelinek <jakub@redhat.com>
* tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): Add offseti
argument. Change pd argument so that it can be modified. Turn
constant non-CONSTRUCTOR store into non-constant if it is too large.
Adjust offset and size of CONSTRUCTOR or non-constant store to avoid
overflows.
(vn_walk_cb_data::vn_walk_cb_data, vn_reference_lookup_3): Adjust
callers.
2020-02-04 Richard Biener <rguenther@suse.de> 2020-02-04 Richard Biener <rguenther@suse.de>
PR tree-optimization/93964 PR tree-optimization/93964
......
...@@ -1716,7 +1716,7 @@ struct vn_walk_cb_data ...@@ -1716,7 +1716,7 @@ struct vn_walk_cb_data
else else
pd.offset = pos; pd.offset = pos;
pd.size = tz; pd.size = tz;
void *r = push_partial_def (pd, 0, 0, prec); void *r = push_partial_def (pd, 0, 0, 0, prec);
gcc_assert (r == NULL_TREE); gcc_assert (r == NULL_TREE);
} }
pos += tz; pos += tz;
...@@ -1733,8 +1733,9 @@ struct vn_walk_cb_data ...@@ -1733,8 +1733,9 @@ struct vn_walk_cb_data
} }
~vn_walk_cb_data (); ~vn_walk_cb_data ();
void *finish (alias_set_type, alias_set_type, tree); void *finish (alias_set_type, alias_set_type, tree);
void *push_partial_def (const pd_data& pd, void *push_partial_def (pd_data pd,
alias_set_type, alias_set_type, HOST_WIDE_INT); alias_set_type, alias_set_type, HOST_WIDE_INT,
HOST_WIDE_INT);
vn_reference_t vr; vn_reference_t vr;
ao_ref orig_ref; ao_ref orig_ref;
...@@ -1817,8 +1818,9 @@ pd_tree_dealloc (void *, void *) ...@@ -1817,8 +1818,9 @@ pd_tree_dealloc (void *, void *)
on failure. */ on failure. */
void * void *
vn_walk_cb_data::push_partial_def (const pd_data &pd, vn_walk_cb_data::push_partial_def (pd_data pd,
alias_set_type set, alias_set_type base_set, alias_set_type set, alias_set_type base_set,
HOST_WIDE_INT offseti,
HOST_WIDE_INT maxsizei) HOST_WIDE_INT maxsizei)
{ {
const HOST_WIDE_INT bufsize = 64; const HOST_WIDE_INT bufsize = 64;
...@@ -1831,6 +1833,27 @@ vn_walk_cb_data::push_partial_def (const pd_data &pd, ...@@ -1831,6 +1833,27 @@ vn_walk_cb_data::push_partial_def (const pd_data &pd,
|| BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN) || BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
return (void *)-1; return (void *)-1;
/* Turn too large constant stores into non-constant stores. */
if (CONSTANT_CLASS_P (pd.rhs) && pd.size > bufsize * BITS_PER_UNIT)
pd.rhs = error_mark_node;
/* And for non-constant or CONSTRUCTOR stores shrink them to only keep at
most a partial byte before and/or after the region. */
if (!CONSTANT_CLASS_P (pd.rhs))
{
if (pd.offset < offseti)
{
HOST_WIDE_INT o = ROUND_DOWN (offseti - pd.offset, BITS_PER_UNIT);
gcc_assert (pd.size > o);
pd.size -= o;
pd.offset += o;
}
if (pd.size > maxsizei)
pd.size = maxsizei + ((pd.size - maxsizei) % BITS_PER_UNIT);
}
pd.offset -= offseti;
bool pd_constant_p = (TREE_CODE (pd.rhs) == CONSTRUCTOR bool pd_constant_p = (TREE_CODE (pd.rhs) == CONSTRUCTOR
|| CONSTANT_CLASS_P (pd.rhs)); || CONSTANT_CLASS_P (pd.rhs));
if (partial_defs.is_empty ()) if (partial_defs.is_empty ())
...@@ -2736,9 +2759,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, ...@@ -2736,9 +2759,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
{ {
pd_data pd; pd_data pd;
pd.rhs = build_constructor (NULL_TREE, NULL); pd.rhs = build_constructor (NULL_TREE, NULL);
pd.offset = offset2i - offseti; pd.offset = offset2i;
pd.size = leni << LOG2_BITS_PER_UNIT; pd.size = leni << LOG2_BITS_PER_UNIT;
return data->push_partial_def (pd, 0, 0, maxsizei); return data->push_partial_def (pd, 0, 0, offseti, maxsizei);
} }
} }
...@@ -2785,11 +2808,11 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, ...@@ -2785,11 +2808,11 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
by a later def. */ by a later def. */
pd_data pd; pd_data pd;
pd.rhs = gimple_assign_rhs1 (def_stmt); pd.rhs = gimple_assign_rhs1 (def_stmt);
pd.offset = offset2i - offseti; pd.offset = offset2i;
pd.size = size2i; pd.size = size2i;
return data->push_partial_def (pd, ao_ref_alias_set (&lhs_ref), return data->push_partial_def (pd, ao_ref_alias_set (&lhs_ref),
ao_ref_base_alias_set (&lhs_ref), ao_ref_base_alias_set (&lhs_ref),
maxsizei); offseti, maxsizei);
} }
} }
} }
...@@ -2936,11 +2959,11 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, ...@@ -2936,11 +2959,11 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
if (TREE_CODE (rhs) == SSA_NAME) if (TREE_CODE (rhs) == SSA_NAME)
rhs = SSA_VAL (rhs); rhs = SSA_VAL (rhs);
pd.rhs = rhs; pd.rhs = rhs;
pd.offset = offset2i - offseti; pd.offset = offset2i;
pd.size = size2i; pd.size = size2i;
return data->push_partial_def (pd, ao_ref_alias_set (&lhs_ref), return data->push_partial_def (pd, ao_ref_alias_set (&lhs_ref),
ao_ref_base_alias_set (&lhs_ref), ao_ref_base_alias_set (&lhs_ref),
maxsizei); offseti, maxsizei);
} }
} }
} }
...@@ -3014,11 +3037,11 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, ...@@ -3014,11 +3037,11 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
{ {
pd_data pd; pd_data pd;
pd.rhs = SSA_VAL (def_rhs); pd.rhs = SSA_VAL (def_rhs);
pd.offset = offset2i - offseti; pd.offset = offset2i;
pd.size = size2i; pd.size = size2i;
return data->push_partial_def (pd, ao_ref_alias_set (&lhs_ref), return data->push_partial_def (pd, ao_ref_alias_set (&lhs_ref),
ao_ref_base_alias_set (&lhs_ref), ao_ref_base_alias_set (&lhs_ref),
maxsizei); offseti, maxsizei);
} }
} }
} }
...@@ -3154,7 +3177,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, ...@@ -3154,7 +3177,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
pd.size = maxsizei; pd.size = maxsizei;
return data->push_partial_def (pd, ao_ref_alias_set (&lhs_ref), return data->push_partial_def (pd, ao_ref_alias_set (&lhs_ref),
ao_ref_base_alias_set (&lhs_ref), ao_ref_base_alias_set (&lhs_ref),
maxsizei); 0, maxsizei);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment