Skip to content

Commit 41e4d92

Browse files
author
Robert Marsh
committed
C++: alias and side effect info for pure functions
1 parent ea7602b commit 41e4d92

File tree

3 files changed

+83
-40
lines changed

3 files changed

+83
-40
lines changed

cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import semmle.code.cpp.models.interfaces.ArrayFunction
22
import semmle.code.cpp.models.interfaces.Taint
3+
import semmle.code.cpp.models.interfaces.Alias
4+
import semmle.code.cpp.models.interfaces.SideEffect
35

4-
class PureFunction extends ArrayFunction, TaintFunction {
5-
PureFunction() {
6+
class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction {
7+
PureStrFunction() {
68
exists(string name |
79
hasName(name) and
810
(
9-
name = "abs"
10-
or name = "atof"
11+
name = "atof"
1112
or name = "atoi"
1213
or name = "atol"
1314
or name = "atoll"
14-
or name = "labs"
1515
or name = "strcasestr"
1616
or name = "strchnul"
1717
or name = "strchr"
@@ -54,4 +54,51 @@ class PureFunction extends ArrayFunction, TaintFunction {
5454
output.isOutReturnValue()
5555
)
5656
}
57+
58+
override predicate parameterNeverEscapes(int i) {
59+
getParameter(i).getUnspecifiedType() instanceof PointerType
60+
}
61+
62+
override predicate parameterEscapesOnlyViaReturn(int i) {
63+
none()
64+
}
65+
66+
override predicate parameterIsAlwaysReturned(int i) {
67+
none()
68+
}
69+
70+
override predicate neverReadsMemory() {
71+
none()
72+
}
73+
74+
override predicate neverWritesMemory() {
75+
any()
76+
}
77+
}
78+
79+
class PureFunction extends TaintFunction, SideEffectFunction {
80+
PureFunction() {
81+
exists(string name |
82+
hasName(name) and
83+
(
84+
name = "abs" or
85+
name = "labs"
86+
)
87+
)
88+
}
89+
90+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
91+
exists (ParameterIndex i |
92+
input.isInParameter(i)
93+
) and
94+
output.isOutReturnValue()
95+
}
96+
97+
override predicate neverReadsMemory() {
98+
any()
99+
}
100+
101+
override predicate neverWritesMemory() {
102+
any()
103+
}
57104
}

cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -779,24 +779,21 @@ ssa.cpp:
779779
# 198| r0_15(char *) = Load : &:r0_14, m0_6
780780
# 198| r0_16(char *) = Convert : r0_15
781781
# 198| r0_17(int) = Call : func:r0_10, 0:r0_13, 1:r0_16
782-
# 198| m0_18(unknown) = ^CallSideEffect : ~m0_1
783-
# 198| m0_19(unknown) = Chi : total:m0_1, partial:m0_18
784-
# 198| m0_20(int) = Store : &:r0_9, r0_17
785-
# 199| r0_21(glval<unknown>) = FunctionAddress[abs] :
786-
# 199| r0_22(glval<int>) = VariableAddress[x] :
787-
# 199| r0_23(int) = Load : &:r0_22, m0_8
788-
# 199| r0_24(int) = Call : func:r0_21, 0:r0_23
789-
# 199| m0_25(unknown) = ^CallSideEffect : ~m0_19
790-
# 199| m0_26(unknown) = Chi : total:m0_19, partial:m0_25
791-
# 199| r0_27(glval<int>) = VariableAddress[ret] :
792-
# 199| r0_28(int) = Load : &:r0_27, m0_20
793-
# 199| r0_29(int) = Add : r0_28, r0_24
794-
# 199| m0_30(int) = Store : &:r0_27, r0_29
795-
# 200| r0_31(glval<int>) = VariableAddress[#return] :
796-
# 200| r0_32(glval<int>) = VariableAddress[ret] :
797-
# 200| r0_33(int) = Load : &:r0_32, m0_30
798-
# 200| m0_34(int) = Store : &:r0_31, r0_33
799-
# 197| r0_35(glval<int>) = VariableAddress[#return] :
800-
# 197| v0_36(void) = ReturnValue : &:r0_35, m0_34
801-
# 197| v0_37(void) = UnmodeledUse : mu*
802-
# 197| v0_38(void) = ExitFunction :
782+
# 198| v0_18(void) = ^CallReadSideEffect : ~m0_1
783+
# 198| m0_19(int) = Store : &:r0_9, r0_17
784+
# 199| r0_20(glval<unknown>) = FunctionAddress[abs] :
785+
# 199| r0_21(glval<int>) = VariableAddress[x] :
786+
# 199| r0_22(int) = Load : &:r0_21, m0_8
787+
# 199| r0_23(int) = Call : func:r0_20, 0:r0_22
788+
# 199| r0_24(glval<int>) = VariableAddress[ret] :
789+
# 199| r0_25(int) = Load : &:r0_24, m0_19
790+
# 199| r0_26(int) = Add : r0_25, r0_23
791+
# 199| m0_27(int) = Store : &:r0_24, r0_26
792+
# 200| r0_28(glval<int>) = VariableAddress[#return] :
793+
# 200| r0_29(glval<int>) = VariableAddress[ret] :
794+
# 200| r0_30(int) = Load : &:r0_29, m0_27
795+
# 200| m0_31(int) = Store : &:r0_28, r0_30
796+
# 197| r0_32(glval<int>) = VariableAddress[#return] :
797+
# 197| v0_33(void) = ReturnValue : &:r0_32, m0_31
798+
# 197| v0_34(void) = UnmodeledUse : mu*
799+
# 197| v0_35(void) = ExitFunction :

cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -745,22 +745,21 @@ ssa.cpp:
745745
# 198| r0_15(char *) = Load : &:r0_14, m0_6
746746
# 198| r0_16(char *) = Convert : r0_15
747747
# 198| r0_17(int) = Call : func:r0_10, 0:r0_13, 1:r0_16
748-
# 198| mu0_18(unknown) = ^CallSideEffect : ~mu0_2
748+
# 198| v0_18(void) = ^CallReadSideEffect : ~mu0_2
749749
# 198| m0_19(int) = Store : &:r0_9, r0_17
750750
# 199| r0_20(glval<unknown>) = FunctionAddress[abs] :
751751
# 199| r0_21(glval<int>) = VariableAddress[x] :
752752
# 199| r0_22(int) = Load : &:r0_21, m0_8
753753
# 199| r0_23(int) = Call : func:r0_20, 0:r0_22
754-
# 199| mu0_24(unknown) = ^CallSideEffect : ~mu0_2
755-
# 199| r0_25(glval<int>) = VariableAddress[ret] :
756-
# 199| r0_26(int) = Load : &:r0_25, m0_19
757-
# 199| r0_27(int) = Add : r0_26, r0_23
758-
# 199| m0_28(int) = Store : &:r0_25, r0_27
759-
# 200| r0_29(glval<int>) = VariableAddress[#return] :
760-
# 200| r0_30(glval<int>) = VariableAddress[ret] :
761-
# 200| r0_31(int) = Load : &:r0_30, m0_28
762-
# 200| m0_32(int) = Store : &:r0_29, r0_31
763-
# 197| r0_33(glval<int>) = VariableAddress[#return] :
764-
# 197| v0_34(void) = ReturnValue : &:r0_33, m0_32
765-
# 197| v0_35(void) = UnmodeledUse : mu*
766-
# 197| v0_36(void) = ExitFunction :
754+
# 199| r0_24(glval<int>) = VariableAddress[ret] :
755+
# 199| r0_25(int) = Load : &:r0_24, m0_19
756+
# 199| r0_26(int) = Add : r0_25, r0_23
757+
# 199| m0_27(int) = Store : &:r0_24, r0_26
758+
# 200| r0_28(glval<int>) = VariableAddress[#return] :
759+
# 200| r0_29(glval<int>) = VariableAddress[ret] :
760+
# 200| r0_30(int) = Load : &:r0_29, m0_27
761+
# 200| m0_31(int) = Store : &:r0_28, r0_30
762+
# 197| r0_32(glval<int>) = VariableAddress[#return] :
763+
# 197| v0_33(void) = ReturnValue : &:r0_32, m0_31
764+
# 197| v0_34(void) = UnmodeledUse : mu*
765+
# 197| v0_35(void) = ExitFunction :

0 commit comments

Comments
 (0)