Skip to content

Commit ba5318f

Browse files
authored
Merge pull request #20369 from MathiasVP/value-numbering-unique-irfunc
C++: Protect the value numbering library from instructions with multiple enclosing functions
2 parents 869b7e0 + 4645bd7 commit ba5318f

File tree

3 files changed

+222
-237
lines changed

3 files changed

+222
-237
lines changed

cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll

Lines changed: 74 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ newtype TValueNumber =
4141
) {
4242
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
4343
} or
44-
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
44+
TUniqueValueNumber(Instruction instr) { uniqueValueNumber(instr) }
4545

4646
/**
4747
* A `ConvertInstruction` which converts data of type `T` to data of type `U`
@@ -129,12 +129,14 @@ private predicate filteredNumberableInstruction(Instruction instr) {
129129
count(instr.(InheritanceConversionInstruction).getBaseClass()) != 1 or
130130
count(instr.(InheritanceConversionInstruction).getDerivedClass()) != 1
131131
)
132+
or
133+
count(instr.getEnclosingIRFunction()) != 1
132134
}
133135

134136
private predicate variableAddressValueNumber(
135137
VariableAddressInstruction instr, IRFunction irFunc, Language::AST ast
136138
) {
137-
instr.getEnclosingIRFunction() = irFunc and
139+
unique( | | instr.getEnclosingIRFunction()) = irFunc and
138140
// The underlying AST element is used as value-numbering key instead of the
139141
// `IRVariable` to work around a problem where a variable or expression with
140142
// multiple types gives rise to multiple `IRVariable`s.
@@ -144,7 +146,7 @@ private predicate variableAddressValueNumber(
144146
private predicate initializeParameterValueNumber(
145147
InitializeParameterInstruction instr, IRFunction irFunc, Language::AST var
146148
) {
147-
instr.getEnclosingIRFunction() = irFunc and
149+
unique( | | instr.getEnclosingIRFunction()) = irFunc and
148150
// The underlying AST element is used as value-numbering key instead of the
149151
// `IRVariable` to work around a problem where a variable or expression with
150152
// multiple types gives rise to multiple `IRVariable`s.
@@ -154,15 +156,15 @@ private predicate initializeParameterValueNumber(
154156
private predicate constantValueNumber(
155157
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
156158
) {
157-
instr.getEnclosingIRFunction() = irFunc and
159+
unique( | | instr.getEnclosingIRFunction()) = irFunc and
158160
unique( | | instr.getResultIRType()) = type and
159161
instr.getValue() = value
160162
}
161163

162164
private predicate stringConstantValueNumber(
163165
StringConstantInstruction instr, IRFunction irFunc, IRType type, string value
164166
) {
165-
instr.getEnclosingIRFunction() = irFunc and
167+
unique( | | instr.getEnclosingIRFunction()) = irFunc and
166168
instr.getResultIRType() = type and
167169
instr.getValue().getValue() = value
168170
}
@@ -171,7 +173,7 @@ private predicate fieldAddressValueNumber(
171173
FieldAddressInstruction instr, IRFunction irFunc, Language::Field field,
172174
TValueNumber objectAddress
173175
) {
174-
instr.getEnclosingIRFunction() = irFunc and
176+
unique( | | instr.getEnclosingIRFunction()) = irFunc and
175177
unique( | | instr.getField()) = field and
176178
tvalueNumber(instr.getObjectAddress()) = objectAddress
177179
}
@@ -182,7 +184,7 @@ private predicate binaryValueNumber0(
182184
TValueNumber valueNumber
183185
) {
184186
not instr instanceof PointerArithmeticInstruction and
185-
instr.getEnclosingIRFunction() = irFunc and
187+
unique( | | instr.getEnclosingIRFunction()) = irFunc and
186188
instr.getOpcode() = opcode and
187189
(
188190
isLeft = true and
@@ -206,7 +208,7 @@ private predicate pointerArithmeticValueNumber0(
206208
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize,
207209
boolean isLeft, TValueNumber valueNumber
208210
) {
209-
instr.getEnclosingIRFunction() = irFunc and
211+
unique( | | instr.getEnclosingIRFunction()) = irFunc and
210212
instr.getOpcode() = opcode and
211213
instr.getElementSize() = elementSize and
212214
(
@@ -229,7 +231,7 @@ private predicate pointerArithmeticValueNumber(
229231
private predicate unaryValueNumber(
230232
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber operand
231233
) {
232-
instr.getEnclosingIRFunction() = irFunc and
234+
unique( | | instr.getEnclosingIRFunction()) = irFunc and
233235
not instr instanceof InheritanceConversionInstruction and
234236
not instr instanceof CopyInstruction and
235237
not instr instanceof FieldAddressInstruction and
@@ -242,7 +244,7 @@ private predicate inheritanceConversionValueNumber(
242244
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode,
243245
Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
244246
) {
245-
instr.getEnclosingIRFunction() = irFunc and
247+
unique( | | instr.getEnclosingIRFunction()) = irFunc and
246248
instr.getOpcode() = opcode and
247249
tvalueNumber(instr.getUnary()) = operand and
248250
unique( | | instr.getBaseClass()) = baseClass and
@@ -254,7 +256,7 @@ private predicate loadTotalOverlapValueNumber0(
254256
LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber valueNumber,
255257
boolean isAddress
256258
) {
257-
instr.getEnclosingIRFunction() = irFunc and
259+
unique( | | instr.getEnclosingIRFunction()) = irFunc and
258260
instr.getResultIRType() = type and
259261
(
260262
isAddress = true and
@@ -277,8 +279,7 @@ private predicate loadTotalOverlapValueNumber(
277279
* Holds if `instr` should be assigned a unique value number because this library does not know how
278280
* to determine if two instances of that instruction are equivalent.
279281
*/
280-
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
281-
instr.getEnclosingIRFunction() = irFunc and
282+
private predicate uniqueValueNumber(Instruction instr) {
282283
not instr.getResultIRType() instanceof IRVoidType and
283284
(
284285
not numberableInstruction(instr)
@@ -294,10 +295,8 @@ cached
294295
TValueNumber tvalueNumber(Instruction instr) {
295296
result = nonUniqueValueNumber(instr)
296297
or
297-
exists(IRFunction irFunc |
298-
uniqueValueNumber(instr, irFunc) and
299-
result = TUniqueValueNumber(irFunc, instr)
300-
)
298+
uniqueValueNumber(instr) and
299+
result = TUniqueValueNumber(instr)
301300
}
302301

303302
/**
@@ -311,68 +310,64 @@ TValueNumber tvalueNumberOfOperand(Operand op) { result = tvalueNumber(op.getDef
311310
* value number.
312311
*/
313312
private TValueNumber nonUniqueValueNumber(Instruction instr) {
314-
exists(IRFunction irFunc |
315-
irFunc = instr.getEnclosingIRFunction() and
316-
(
317-
exists(Language::AST ast |
318-
variableAddressValueNumber(instr, irFunc, ast) and
319-
result = TVariableAddressValueNumber(irFunc, ast)
320-
)
321-
or
322-
exists(Language::AST var |
323-
initializeParameterValueNumber(instr, irFunc, var) and
324-
result = TInitializeParameterValueNumber(irFunc, var)
325-
)
326-
or
327-
exists(string value, IRType type |
328-
constantValueNumber(instr, irFunc, type, value) and
329-
result = TConstantValueNumber(irFunc, type, value)
330-
)
331-
or
332-
exists(IRType type, string value |
333-
stringConstantValueNumber(instr, irFunc, type, value) and
334-
result = TStringConstantValueNumber(irFunc, type, value)
335-
)
336-
or
337-
exists(Language::Field field, TValueNumber objectAddress |
338-
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
339-
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
340-
)
341-
or
342-
exists(Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand |
343-
binaryValueNumber(instr, irFunc, opcode, leftOperand, rightOperand) and
344-
result = TBinaryValueNumber(irFunc, opcode, leftOperand, rightOperand)
345-
)
346-
or
347-
exists(Opcode opcode, TValueNumber operand |
348-
unaryValueNumber(instr, irFunc, opcode, operand) and
349-
result = TUnaryValueNumber(irFunc, opcode, operand)
350-
)
351-
or
352-
exists(
353-
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
354-
|
355-
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
356-
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
357-
)
358-
or
359-
exists(Opcode opcode, int elementSize, TValueNumber leftOperand, TValueNumber rightOperand |
360-
pointerArithmeticValueNumber(instr, irFunc, opcode, elementSize, leftOperand, rightOperand) and
361-
result =
362-
TPointerArithmeticValueNumber(irFunc, opcode, elementSize, leftOperand, rightOperand)
363-
)
364-
or
365-
exists(IRType type, TValueNumber memOperand, TValueNumber operand |
366-
loadTotalOverlapValueNumber(instr, irFunc, type, memOperand, operand) and
367-
result = TLoadTotalOverlapValueNumber(irFunc, type, memOperand, operand)
368-
)
369-
or
370-
// The value number of a copy is just the value number of its source value.
371-
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
372-
or
373-
// The value number of a type-preserving conversion is just the value
374-
// number of the unconverted value.
375-
result = tvalueNumber(instr.(TypePreservingConvertInstruction).getUnary())
313+
exists(IRFunction irFunc | irFunc = instr.getEnclosingIRFunction() |
314+
exists(Language::AST ast |
315+
variableAddressValueNumber(instr, irFunc, ast) and
316+
result = TVariableAddressValueNumber(irFunc, ast)
317+
)
318+
or
319+
exists(Language::AST var |
320+
initializeParameterValueNumber(instr, irFunc, var) and
321+
result = TInitializeParameterValueNumber(irFunc, var)
322+
)
323+
or
324+
exists(string value, IRType type |
325+
constantValueNumber(instr, irFunc, type, value) and
326+
result = TConstantValueNumber(irFunc, type, value)
327+
)
328+
or
329+
exists(IRType type, string value |
330+
stringConstantValueNumber(instr, irFunc, type, value) and
331+
result = TStringConstantValueNumber(irFunc, type, value)
332+
)
333+
or
334+
exists(Language::Field field, TValueNumber objectAddress |
335+
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
336+
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
337+
)
338+
or
339+
exists(Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand |
340+
binaryValueNumber(instr, irFunc, opcode, leftOperand, rightOperand) and
341+
result = TBinaryValueNumber(irFunc, opcode, leftOperand, rightOperand)
342+
)
343+
or
344+
exists(Opcode opcode, TValueNumber operand |
345+
unaryValueNumber(instr, irFunc, opcode, operand) and
346+
result = TUnaryValueNumber(irFunc, opcode, operand)
376347
)
348+
or
349+
exists(
350+
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
351+
|
352+
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
353+
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
354+
)
355+
or
356+
exists(Opcode opcode, int elementSize, TValueNumber leftOperand, TValueNumber rightOperand |
357+
pointerArithmeticValueNumber(instr, irFunc, opcode, elementSize, leftOperand, rightOperand) and
358+
result = TPointerArithmeticValueNumber(irFunc, opcode, elementSize, leftOperand, rightOperand)
359+
)
360+
or
361+
exists(IRType type, TValueNumber memOperand, TValueNumber operand |
362+
loadTotalOverlapValueNumber(instr, irFunc, type, memOperand, operand) and
363+
result = TLoadTotalOverlapValueNumber(irFunc, type, memOperand, operand)
364+
)
365+
or
366+
// The value number of a copy is just the value number of its source value.
367+
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
368+
or
369+
// The value number of a type-preserving conversion is just the value
370+
// number of the unconverted value.
371+
result = tvalueNumber(instr.(TypePreservingConvertInstruction).getUnary())
377372
)
378373
}

0 commit comments

Comments
 (0)