Skip to content

Commit 1c8e0c4

Browse files
committed
C++: Fix more inconsistencies.
1 parent 45ba0c3 commit 1c8e0c4

File tree

10 files changed

+142
-14
lines changed

10 files changed

+142
-14
lines changed

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

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,57 @@ private predicate resultEscapesNonReturn(Instruction instr) {
338338
not instr.isResultModeled()
339339
}
340340

341+
/** Holds if `operand` may (transitively) flow to an `AddressOperand` whose use is unmodeled. */
342+
private predicate consumedAsAddressOperand(Operand operand) {
343+
operand instanceof AddressOperand and
344+
exists(Instruction use | not use.isResultModeled())
345+
or
346+
exists(Operand address |
347+
consumedAsAddressOperand(address) and
348+
operandIsPropagated(operand, _, address.getDef())
349+
)
350+
}
351+
352+
/**
353+
* Holds if `operand` may originate from a base instruction of an allocation,
354+
* and that operand may transitively flow to an `AddressOperand` whose use is unmodeled.
355+
*/
356+
private predicate propagatedFromAllocationBase(Operand operand, Configuration::Allocation allocation) {
357+
consumedAsAddressOperand(operand) and
358+
(
359+
not exists(Configuration::getOldAllocation(allocation)) and
360+
operand.getDef() = allocation.getABaseInstruction()
361+
or
362+
exists(Operand address |
363+
operandIsPropagated(address, _, operand.getDef()) and
364+
propagatedFromAllocationBase(address, allocation)
365+
)
366+
)
367+
}
368+
369+
private predicate propagatedFromNonAllocationBase(Operand operand) {
370+
exists(Instruction def |
371+
def = operand.getDef() and
372+
not operandIsPropagated(_, _, def) and
373+
not def = any(Configuration::Allocation allocation).getABaseInstruction()
374+
)
375+
or
376+
exists(Operand address |
377+
operandIsPropagated(address, _, operand.getDef()) and
378+
propagatedFromNonAllocationBase(address)
379+
)
380+
}
381+
382+
/**
383+
* Holds if we cannot see all producers of an operand for which allocation also flows into.
384+
*/
385+
private predicate operandConsumesEscaped(Configuration::Allocation allocation) {
386+
exists(AddressOperand address |
387+
propagatedFromAllocationBase(address, allocation) and
388+
propagatedFromNonAllocationBase(address)
389+
)
390+
}
391+
341392
/**
342393
* Holds if the address of `allocation` escapes outside the domain of the analysis. This can occur
343394
* either because the allocation's address is taken within the function and escapes, or because the
@@ -346,12 +397,14 @@ private predicate resultEscapesNonReturn(Instruction instr) {
346397
predicate allocationEscapes(Configuration::Allocation allocation) {
347398
allocation.alwaysEscapes()
348399
or
349-
exists(IREscapeAnalysisConfiguration config |
350-
config.useSoundEscapeAnalysis() and resultEscapesNonReturn(allocation.getABaseInstruction())
400+
exists(IREscapeAnalysisConfiguration config | config.useSoundEscapeAnalysis() |
401+
resultEscapesNonReturn(allocation.getABaseInstruction())
402+
or
403+
operandConsumesEscaped(allocation)
351404
)
352405
or
353406
Configuration::phaseNeedsSoundEscapeAnalysis() and
354-
resultEscapesNonReturn(allocation.getABaseInstruction())
407+
(resultEscapesNonReturn(allocation.getABaseInstruction()) or operandConsumesEscaped(allocation))
355408
}
356409

357410
/**

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,8 @@ class DynamicAllocation extends Allocation, TDynamicAllocation {
146146
}
147147

148148
predicate phaseNeedsSoundEscapeAnalysis() { none() }
149+
150+
UnaliasedSsa::Allocation getOldAllocation(VariableAllocation allocation) {
151+
UnaliasedSsa::canReuseSsaForVariable(allocation.getIRVariable()) and
152+
result = allocation.getIRVariable()
153+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConst
77
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
88
private import semmle.code.cpp.ir.internal.IntegerInterval as Interval
99
private import semmle.code.cpp.ir.implementation.internal.OperandTag
10-
private import AliasConfiguration
10+
import AliasConfiguration
1111
private import codeql.util.Boolean
1212

1313
private class IntValue = Ints::IntValue;

cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,57 @@ private predicate resultEscapesNonReturn(Instruction instr) {
338338
not instr.isResultModeled()
339339
}
340340

341+
/** Holds if `operand` may (transitively) flow to an `AddressOperand` whose use is unmodeled. */
342+
private predicate consumedAsAddressOperand(Operand operand) {
343+
operand instanceof AddressOperand and
344+
exists(Instruction use | not use.isResultModeled())
345+
or
346+
exists(Operand address |
347+
consumedAsAddressOperand(address) and
348+
operandIsPropagated(operand, _, address.getDef())
349+
)
350+
}
351+
352+
/**
353+
* Holds if `operand` may originate from a base instruction of an allocation,
354+
* and that operand may transitively flow to an `AddressOperand` whose use is unmodeled.
355+
*/
356+
private predicate propagatedFromAllocationBase(Operand operand, Configuration::Allocation allocation) {
357+
consumedAsAddressOperand(operand) and
358+
(
359+
not exists(Configuration::getOldAllocation(allocation)) and
360+
operand.getDef() = allocation.getABaseInstruction()
361+
or
362+
exists(Operand address |
363+
operandIsPropagated(address, _, operand.getDef()) and
364+
propagatedFromAllocationBase(address, allocation)
365+
)
366+
)
367+
}
368+
369+
private predicate propagatedFromNonAllocationBase(Operand operand) {
370+
exists(Instruction def |
371+
def = operand.getDef() and
372+
not operandIsPropagated(_, _, def) and
373+
not def = any(Configuration::Allocation allocation).getABaseInstruction()
374+
)
375+
or
376+
exists(Operand address |
377+
operandIsPropagated(address, _, operand.getDef()) and
378+
propagatedFromNonAllocationBase(address)
379+
)
380+
}
381+
382+
/**
383+
* Holds if we cannot see all producers of an operand for which allocation also flows into.
384+
*/
385+
private predicate operandConsumesEscaped(Configuration::Allocation allocation) {
386+
exists(AddressOperand address |
387+
propagatedFromAllocationBase(address, allocation) and
388+
propagatedFromNonAllocationBase(address)
389+
)
390+
}
391+
341392
/**
342393
* Holds if the address of `allocation` escapes outside the domain of the analysis. This can occur
343394
* either because the allocation's address is taken within the function and escapes, or because the
@@ -346,12 +397,14 @@ private predicate resultEscapesNonReturn(Instruction instr) {
346397
predicate allocationEscapes(Configuration::Allocation allocation) {
347398
allocation.alwaysEscapes()
348399
or
349-
exists(IREscapeAnalysisConfiguration config |
350-
config.useSoundEscapeAnalysis() and resultEscapesNonReturn(allocation.getABaseInstruction())
400+
exists(IREscapeAnalysisConfiguration config | config.useSoundEscapeAnalysis() |
401+
resultEscapesNonReturn(allocation.getABaseInstruction())
402+
or
403+
operandConsumesEscaped(allocation)
351404
)
352405
or
353406
Configuration::phaseNeedsSoundEscapeAnalysis() and
354-
resultEscapesNonReturn(allocation.getABaseInstruction())
407+
(resultEscapesNonReturn(allocation.getABaseInstruction()) or operandConsumesEscaped(allocation))
355408
}
356409

357410
/**

cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasConfiguration.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
private import AliasConfigurationImports
2+
private import codeql.util.Unit
23

34
/**
45
* A memory allocation that can be tracked by the SimpleSSA alias analysis.
@@ -16,3 +17,5 @@ class Allocation extends IRAutomaticVariable {
1617
}
1718

1819
predicate phaseNeedsSoundEscapeAnalysis() { any() }
20+
21+
Unit getOldAllocation(Allocation allocation) { any() }

cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import AliasAnalysis
22
private import SimpleSSAImports
33
import SimpleSSAPublicImports
4-
private import AliasConfiguration
4+
import AliasConfiguration
55
private import codeql.util.Unit
66

77
private predicate isTotalAccess(Allocation var, AddressOperand addrOperand, IRType type) {

cpp/ql/test/library-tests/ir/ir/aliased_ir.expected

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18827,22 +18827,23 @@ ir.cpp:
1882718827
# 2667| r2667_1(glval<int>) = VariableAddress[intBuffer] :
1882818828
# 2667| r2667_2(int) = Constant[8] :
1882918829
# 2667| m2667_3(int) = Store[intBuffer] : &:r2667_1, r2667_2
18830+
# 2667| m2667_4(unknown) = Chi : total:m2663_4, partial:m2667_3
1883018831
# 2668| r2668_1(glval<int>) = VariableAddress[intBuffer] :
1883118832
# 2668| r2668_2(int *) = CopyValue : r2668_1
1883218833
# 2668| r2668_3(glval<int *>) = VariableAddress[data] :
1883318834
# 2668| m2668_4(int *) = Store[data] : &:r2668_3, r2668_2
1883418835
#-----| Goto -> Block 2
1883518836

1883618837
# 2670| Block 2
18837-
# 2670| m2670_1(int) = Phi : from 1:m2667_3
18838+
# 2670| m2670_1(unknown) = Phi : from 0:~m2663_4, from 1:~m2667_4
1883818839
# 2670| m2670_2(int *) = Phi : from 0:m2665_3, from 1:m2668_4
1883918840
# 2670| r2670_3(glval<unknown>) = FunctionAddress[use_int] :
1884018841
# 2670| r2670_4(glval<int *>) = VariableAddress[data] :
1884118842
# 2670| r2670_5(int *) = Load[data] : &:r2670_4, m2670_2
1884218843
# 2670| r2670_6(int) = Load[?] : &:r2670_5, ~m2670_1
1884318844
# 2670| v2670_7(void) = Call[use_int] : func:r2670_3, 0:r2670_6
18844-
# 2670| m2670_8(unknown) = ^CallSideEffect : ~m2663_4
18845-
# 2670| m2670_9(unknown) = Chi : total:m2663_4, partial:m2670_8
18845+
# 2670| m2670_8(unknown) = ^CallSideEffect : ~m2670_1
18846+
# 2670| m2670_9(unknown) = Chi : total:m2670_1, partial:m2670_8
1884618847
# 2671| v2671_1(void) = NoOp :
1884718848
# 2663| v2663_7(void) = ReturnVoid :
1884818849
# 2663| v2663_8(void) = AliasedUse : ~m2670_9

cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ missingOperand
22
unexpectedOperand
33
duplicateOperand
44
missingPhiOperand
5-
| ir.cpp:2670:3:2670:9 | Phi: call to use_int | Instruction 'Phi: call to use_int' is missing an operand for predecessor block 'EnterFunction: phi_with_single_input_at_merge' in function '$@'. | ir.cpp:2663:13:2663:42 | void phi_with_single_input_at_merge(bool) | void phi_with_single_input_at_merge(bool) |
65
missingOperandType
76
duplicateChiOperand
87
sideEffectWithoutPrimary

cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ missingOperand
22
unexpectedOperand
33
duplicateOperand
44
missingPhiOperand
5-
| ir.cpp:2670:3:2670:9 | Phi: call to use_int | Instruction 'Phi: call to use_int' is missing an operand for predecessor block 'EnterFunction: phi_with_single_input_at_merge' in function '$@'. | ir.cpp:2663:13:2663:42 | void phi_with_single_input_at_merge(bool) | void phi_with_single_input_at_merge(bool) |
65
missingOperandType
76
duplicateChiOperand
87
sideEffectWithoutPrimary

cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/tests/test.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,4 +565,19 @@ void test45() {
565565

566566
*rP = NULL;
567567
use(r); // GOOD
568-
}
568+
}
569+
570+
void test46()
571+
{
572+
LinkedList *r, **rP = &r;
573+
574+
while (getBool())
575+
{
576+
LinkedList *s = nullptr;
577+
*rP = s;
578+
rP = &s->next;
579+
}
580+
581+
*rP = nullptr;
582+
use(r);
583+
}

0 commit comments

Comments
 (0)