spirv-fuzz: Fix memory management in the fact manager (#3313)

Fixes a bug where, while recursively adding id equation facts, a
reference to a set of id equations could be used after it had been
freed (due to equivalence classes of equations being merged).
This commit is contained in:
Alastair Donaldson 2020-04-27 14:24:11 +01:00 committed by GitHub
parent d158ffe540
commit b74199a22d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -430,6 +430,9 @@ class FactManager::DataSynonymAndIdEquationFacts {
uint32_t maximum_equivalence_class_size); uint32_t maximum_equivalence_class_size);
private: private:
using OperationSet =
std::unordered_set<Operation, OperationHash, OperationEquals>;
// Adds the synonym |dd1| = |dd2| to the set of managed facts, and recurses // Adds the synonym |dd1| = |dd2| to the set of managed facts, and recurses
// into sub-components of the data descriptors, if they are composites, to // into sub-components of the data descriptors, if they are composites, to
// record that their components are pairwise-synonymous. // record that their components are pairwise-synonymous.
@ -448,6 +451,8 @@ class FactManager::DataSynonymAndIdEquationFacts {
opt::IRContext* context, const protobufs::DataDescriptor& dd1, opt::IRContext* context, const protobufs::DataDescriptor& dd1,
const protobufs::DataDescriptor& dd2) const; const protobufs::DataDescriptor& dd2) const;
OperationSet GetEquations(const protobufs::DataDescriptor* lhs) const;
// Requires that |lhs_dd| and every element of |rhs_dds| is present in the // Requires that |lhs_dd| and every element of |rhs_dds| is present in the
// |synonymous_| equivalence relation, but is not necessarily its own // |synonymous_| equivalence relation, but is not necessarily its own
// representative. Records the fact that the equation // representative. Records the fact that the equation
@ -480,9 +485,7 @@ class FactManager::DataSynonymAndIdEquationFacts {
// All data descriptors occurring in equations are required to be present in // All data descriptors occurring in equations are required to be present in
// the |synonymous_| equivalence relation, and to be their own representatives // the |synonymous_| equivalence relation, and to be their own representatives
// in that relation. // in that relation.
std::unordered_map< std::unordered_map<const protobufs::DataDescriptor*, OperationSet>
const protobufs::DataDescriptor*,
std::unordered_set<Operation, OperationHash, OperationEquals>>
id_equations_; id_equations_;
}; };
@ -520,6 +523,16 @@ void FactManager::DataSynonymAndIdEquationFacts::AddFact(
rhs_dd_ptrs, context); rhs_dd_ptrs, context);
} }
FactManager::DataSynonymAndIdEquationFacts::OperationSet
FactManager::DataSynonymAndIdEquationFacts::GetEquations(
const protobufs::DataDescriptor* lhs) const {
auto existing = id_equations_.find(lhs);
if (existing == id_equations_.end()) {
return OperationSet();
}
return existing->second;
}
void FactManager::DataSynonymAndIdEquationFacts::AddEquationFactRecursive( void FactManager::DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
const protobufs::DataDescriptor& lhs_dd, SpvOp opcode, const protobufs::DataDescriptor& lhs_dd, SpvOp opcode,
const std::vector<const protobufs::DataDescriptor*>& rhs_dds, const std::vector<const protobufs::DataDescriptor*>& rhs_dds,
@ -538,9 +551,7 @@ void FactManager::DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
if (id_equations_.count(lhs_dd_representative) == 0) { if (id_equations_.count(lhs_dd_representative) == 0) {
// We have not seen an equation with this LHS before, so associate the LHS // We have not seen an equation with this LHS before, so associate the LHS
// with an initially empty set. // with an initially empty set.
id_equations_.insert( id_equations_.insert({lhs_dd_representative, OperationSet()});
{lhs_dd_representative,
std::unordered_set<Operation, OperationHash, OperationEquals>()});
} }
{ {
@ -562,44 +573,29 @@ void FactManager::DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
switch (opcode) { switch (opcode) {
case SpvOpIAdd: { case SpvOpIAdd: {
// Equation form: "a = b + c" // Equation form: "a = b + c"
{ for (auto equation : GetEquations(rhs_dds[0])) {
auto existing_first_operand_equations = id_equations_.find(rhs_dds[0]); if (equation.opcode == SpvOpISub) {
if (existing_first_operand_equations != id_equations_.end()) { // Equation form: "a = (d - e) + c"
for (auto equation : existing_first_operand_equations->second) { if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[1])) {
if (equation.opcode == SpvOpISub) { // Equation form: "a = (d - c) + c"
// Equation form: "a = (d - e) + c" // We can thus infer "a = d"
if (synonymous_.IsEquivalent(*equation.operands[1], AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], context);
*rhs_dds[1])) { }
// Equation form: "a = (d - c) + c" if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
// We can thus infer "a = d" // Equation form: "a = (c - e) + c"
AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], // We can thus infer "a = -e"
context); AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
} {equation.operands[1]}, context);
if (synonymous_.IsEquivalent(*equation.operands[0],
*rhs_dds[1])) {
// Equation form: "a = (c - e) + c"
// We can thus infer "a = -e"
AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
{equation.operands[1]}, context);
}
}
} }
} }
} }
{ for (auto equation : GetEquations(rhs_dds[1])) {
auto existing_second_operand_equations = id_equations_.find(rhs_dds[1]); if (equation.opcode == SpvOpISub) {
if (existing_second_operand_equations != id_equations_.end()) { // Equation form: "a = b + (d - e)"
for (auto equation : existing_second_operand_equations->second) { if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[0])) {
if (equation.opcode == SpvOpISub) { // Equation form: "a = b + (d - b)"
// Equation form: "a = b + (d - e)" // We can thus infer "a = d"
if (synonymous_.IsEquivalent(*equation.operands[1], AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], context);
*rhs_dds[0])) {
// Equation form: "a = b + (d - b)"
// We can thus infer "a = d"
AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0],
context);
}
}
} }
} }
} }
@ -607,73 +603,54 @@ void FactManager::DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
} }
case SpvOpISub: { case SpvOpISub: {
// Equation form: "a = b - c" // Equation form: "a = b - c"
{ for (auto equation : GetEquations(rhs_dds[0])) {
auto existing_first_operand_equations = id_equations_.find(rhs_dds[0]); if (equation.opcode == SpvOpIAdd) {
if (existing_first_operand_equations != id_equations_.end()) { // Equation form: "a = (d + e) - c"
for (auto equation : existing_first_operand_equations->second) { if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
if (equation.opcode == SpvOpIAdd) { // Equation form: "a = (c + e) - c"
// Equation form: "a = (d + e) - c" // We can thus infer "a = e"
if (synonymous_.IsEquivalent(*equation.operands[0], AddDataSynonymFactRecursive(lhs_dd, *equation.operands[1], context);
*rhs_dds[1])) { }
// Equation form: "a = (c + e) - c" if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[1])) {
// We can thus infer "a = e" // Equation form: "a = (d + c) - c"
AddDataSynonymFactRecursive(lhs_dd, *equation.operands[1], // We can thus infer "a = d"
context); AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], context);
} }
if (synonymous_.IsEquivalent(*equation.operands[1], }
*rhs_dds[1])) {
// Equation form: "a = (d + c) - c"
// We can thus infer "a = d"
AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0],
context);
}
}
if (equation.opcode == SpvOpISub) { if (equation.opcode == SpvOpISub) {
// Equation form: "a = (d - e) - c" // Equation form: "a = (d - e) - c"
if (synonymous_.IsEquivalent(*equation.operands[0], if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
*rhs_dds[1])) { // Equation form: "a = (c - e) - c"
// Equation form: "a = (c - e) - c" // We can thus infer "a = -e"
// We can thus infer "a = -e" AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
AddEquationFactRecursive(lhs_dd, SpvOpSNegate, {equation.operands[1]}, context);
{equation.operands[1]}, context);
}
}
} }
} }
} }
{ for (auto equation : GetEquations(rhs_dds[1])) {
auto existing_second_operand_equations = id_equations_.find(rhs_dds[1]); if (equation.opcode == SpvOpIAdd) {
if (existing_second_operand_equations != id_equations_.end()) { // Equation form: "a = b - (d + e)"
for (auto equation : existing_second_operand_equations->second) { if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[0])) {
if (equation.opcode == SpvOpIAdd) { // Equation form: "a = b - (b + e)"
// Equation form: "a = b - (d + e)" // We can thus infer "a = -e"
if (synonymous_.IsEquivalent(*equation.operands[0], AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
*rhs_dds[0])) { {equation.operands[1]}, context);
// Equation form: "a = b - (b + e)" }
// We can thus infer "a = -e" if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[0])) {
AddEquationFactRecursive(lhs_dd, SpvOpSNegate, // Equation form: "a = b - (d + b)"
{equation.operands[1]}, context); // We can thus infer "a = -d"
} AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
if (synonymous_.IsEquivalent(*equation.operands[1], {equation.operands[0]}, context);
*rhs_dds[0])) { }
// Equation form: "a = b - (d + b)" }
// We can thus infer "a = -d" if (equation.opcode == SpvOpISub) {
AddEquationFactRecursive(lhs_dd, SpvOpSNegate, // Equation form: "a = b - (d - e)"
{equation.operands[0]}, context); if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[0])) {
} // Equation form: "a = b - (b - e)"
} // We can thus infer "a = e"
if (equation.opcode == SpvOpISub) { AddDataSynonymFactRecursive(lhs_dd, *equation.operands[1], context);
// Equation form: "a = b - (d - e)"
if (synonymous_.IsEquivalent(*equation.operands[0],
*rhs_dds[0])) {
// Equation form: "a = b - (b - e)"
// We can thus infer "a = e"
AddDataSynonymFactRecursive(lhs_dd, *equation.operands[1],
context);
}
}
} }
} }
} }
@ -682,14 +659,11 @@ void FactManager::DataSynonymAndIdEquationFacts::AddEquationFactRecursive(
case SpvOpLogicalNot: case SpvOpLogicalNot:
case SpvOpSNegate: { case SpvOpSNegate: {
// Equation form: "a = !b" or "a = -b" // Equation form: "a = !b" or "a = -b"
auto existing_equations = id_equations_.find(rhs_dds[0]); for (auto equation : GetEquations(rhs_dds[0])) {
if (existing_equations != id_equations_.end()) { if (equation.opcode == opcode) {
for (auto equation : existing_equations->second) { // Equation form: "a = !!b" or "a = -(-b)"
if (equation.opcode == opcode) { // We can thus infer "a = b"
// Equation form: "a = !!b" or "a = -(-b)" AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], context);
// We can thus infer "a = b"
AddDataSynonymFactRecursive(lhs_dd, *equation.operands[0], context);
}
} }
} }
break; break;
@ -1116,9 +1090,7 @@ void FactManager::DataSynonymAndIdEquationFacts::MakeEquivalent(
// equations about |still_representative|; create an empty set of equations // equations about |still_representative|; create an empty set of equations
// if this is the case. // if this is the case.
if (!id_equations_.count(still_representative)) { if (!id_equations_.count(still_representative)) {
id_equations_.insert( id_equations_.insert({still_representative, OperationSet()});
{still_representative,
std::unordered_set<Operation, OperationHash, OperationEquals>()});
} }
auto still_representative_id_equations = auto still_representative_id_equations =
id_equations_.find(still_representative); id_equations_.find(still_representative);