Skip to content

Commit 84b39bf

Browse files
C++: Simplify models for side effects and alias info.
1 parent 2b80aee commit 84b39bf

4 files changed

Lines changed: 60 additions & 130 deletions

File tree

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,11 +308,11 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
308308
}
309309

310310
override predicate hasReadSideEffect() {
311-
SideEffectModel::functionReadsMemory(funcCall.getTarget())
311+
not funcCall.getTarget().(SideEffectFunction).neverReadsMemory()
312312
}
313313

314314
override predicate hasWriteSideEffect() {
315-
SideEffectModel::functionWritesMemory(funcCall.getTarget())
315+
not funcCall.getTarget().(SideEffectFunction).neverWritesMemory()
316316
}
317317
}
318318

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

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ import semmle.code.cpp.models.interfaces.SideEffect
66
/**
77
* The standard function templates `std::move` and `std::identity`
88
*/
9-
class IdentityFunction extends DataFlowFunction, SideEffectModel::SideEffectFunction,
10-
AliasModel::AliasFunction {
9+
class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction {
1110
IdentityFunction() {
1211
this.getNamespace().getParentNamespace() instanceof GlobalNamespace and
1312
this.getNamespace().getName() = "std" and
@@ -17,23 +16,25 @@ class IdentityFunction extends DataFlowFunction, SideEffectModel::SideEffectFunc
1716
)
1817
}
1918

20-
override predicate readsMemory() {
21-
none()
19+
override predicate neverReadsMemory() {
20+
any()
21+
}
22+
23+
override predicate neverWritesMemory() {
24+
any()
2225
}
2326

24-
override predicate writesMemory() {
27+
override predicate parameterNeverEscapes(int index) {
2528
none()
2629
}
2730

28-
override AliasModel::ParameterEscape getParameterEscapeBehavior(int index) {
29-
exists(getParameter(index)) and
30-
if index = 0 then
31-
result instanceof AliasModel::EscapesOnlyViaReturn
32-
else
33-
result instanceof AliasModel::DoesNotEscape
31+
override predicate parameterEscapesOnlyViaReturn(int index) {
32+
// These functions simply return the argument value.
33+
index = 0
3434
}
3535

3636
override predicate parameterIsAlwaysReturned(int index) {
37+
// These functions simply return the argument value.
3738
index = 0
3839
}
3940

cpp/ql/src/semmle/code/cpp/models/interfaces/Alias.qll

Lines changed: 35 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -10,92 +10,45 @@
1010
import semmle.code.cpp.Function
1111
import semmle.code.cpp.models.Models
1212

13-
module AliasModel {
14-
private newtype TParameterEscape =
15-
TDoesNotEscape() or
16-
TEscapesOnlyViaReturn() or
17-
TEscapes()
18-
19-
class ParameterEscape extends TParameterEscape {
20-
string toString() {
21-
result = "Unknown"
22-
}
23-
}
24-
25-
class DoesNotEscape extends ParameterEscape, TDoesNotEscape {
26-
override string toString() {
27-
result = "DoesNotEscape"
28-
}
29-
}
30-
31-
class EscapesOnlyViaReturn extends ParameterEscape, TEscapesOnlyViaReturn {
32-
override string toString() {
33-
result = "EscapesOnlyViaReturn"
34-
}
35-
}
36-
37-
class Escapes extends ParameterEscape, TEscapes {
38-
override string toString() {
39-
result = "Escapes"
40-
}
41-
}
42-
13+
/**
14+
* Models the aliasing behavior of a library function.
15+
*/
16+
abstract class AliasFunction extends Function {
4317
/**
44-
* Models the aliasing behavior of a library function.
45-
*/
46-
abstract class AliasFunction extends Function {
47-
/**
48-
* Specifies whether the address passed to the parameter at the specified index is retained after
49-
* the function returns. The result is given as a `ParameterEscape` object. See the comments for
50-
* that class and its subclasses for a description of each possible result.
51-
*
52-
* Example:
53-
* ```
54-
* int* g;
55-
* int* func(int* p, int* q, int* r, int* s, int n) {
56-
* *s = 1; // `s` does not escape.
57-
* g = p; // Stored in global. `p` escapes.
58-
* if (rand()) {
59-
* return q; // `q` escapes via the return value.
60-
* }
61-
* else {
62-
* return r + n; // `r` escapes via the return value, even though an offset has been added.
63-
* }
64-
* }
65-
* ```
66-
*
67-
* For the above function, the following terms hold:
68-
* - `getParameterEscapeBehavior(0) instanceof Escapes`
69-
* - `getParameterEscapeBehavior(1) instanceof EscapesOnlyViaReturn`
70-
* - `getParameterEscapeBehavior(2) instanceof EscapesOnlyViaReturn`
71-
* - `getParameterEscapeBehavior(3) instanceof DoesNotEscape`
72-
*/
73-
abstract ParameterEscape getParameterEscapeBehavior(int index);
74-
75-
/**
76-
* Holds if the function always returns the value of the parameter at the specified index.
77-
*/
78-
abstract predicate parameterIsAlwaysReturned(int index);
79-
}
18+
* Holds if the address passed to the parameter at the specified index is never retained after
19+
* the function returns.
20+
*
21+
* Example:
22+
* ```
23+
* int* g;
24+
* int* func(int* p, int* q, int* r, int* s, int n) {
25+
* *s = 1; // `s` does not escape.
26+
* g = p; // Stored in global. `p` escapes.
27+
* if (rand()) {
28+
* return q; // `q` escapes via the return value.
29+
* }
30+
* else {
31+
* return r + n; // `r` escapes via the return value, even though an offset has been added.
32+
* }
33+
* }
34+
* ```
35+
*
36+
* For the above function, the following terms hold:
37+
* - `parameterEscapesOnlyViaReturn(1)`
38+
* - `parameterEscapesOnlyViaReturn(2)`
39+
* - `parameterNeverEscapes(3)`
40+
*/
41+
abstract predicate parameterNeverEscapes(int index);
8042

8143
/**
82-
* Specifies whether the address passed to the parameter at the specified index is retained after
83-
* the function returns. The result is given as a `ParameterEscape` object. See the comments for
84-
* that class and its subclasses for a description of each possible result.
85-
*/
86-
ParameterEscape getParameterEscapeBehavior(Function f, int index) {
87-
result = f.(AliasFunction).getParameterEscapeBehavior(index) or
88-
(
89-
not f instanceof AliasFunction and
90-
exists(f.getParameter(index)) and
91-
result instanceof Escapes
92-
)
93-
}
44+
* Holds if the address passed to the parameter at the specified index escapes via the return
45+
* value of the function, but does not otherwise escape. See the comment for
46+
* `parameterNeverEscapes` for an example.
47+
*/
48+
abstract predicate parameterEscapesOnlyViaReturn(int index);
9449

9550
/**
9651
* Holds if the function always returns the value of the parameter at the specified index.
9752
*/
98-
predicate parameterIsAlwaysReturned(Function f, int index) {
99-
f.(AliasFunction).parameterIsAlwaysReturned(index)
100-
}
101-
}
53+
abstract predicate parameterIsAlwaysReturned(int index);
54+
}

cpp/ql/src/semmle/code/cpp/models/interfaces/SideEffect.qll

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,45 +10,21 @@
1010
import semmle.code.cpp.Function
1111
import semmle.code.cpp.models.Models
1212

13-
module SideEffectModel {
14-
/**
15-
* Models the side effects of a library function.
16-
*/
17-
abstract class SideEffectFunction extends Function {
18-
/**
19-
* Holds if the function may read from memory that was defined before entry to the function. This
20-
* memory could be from global variables, or from other memory that was reachable from a pointer
21-
* that was passed into the function.
22-
*/
23-
abstract predicate readsMemory();
24-
25-
/**
26-
* Holds if the function may write to memory that remains allocated after the function returns.
27-
* This memory could be from global variables, or from other memory that was reachable from a
28-
* pointer that was passed into the function.
29-
*/
30-
abstract predicate writesMemory();
31-
}
32-
13+
/**
14+
* Models the side effects of a library function.
15+
*/
16+
abstract class SideEffectFunction extends Function {
3317
/**
34-
* Holds if the function `f` may read from memory that was defined before entry to the function.
18+
* Holds if the function never reads from memory that was defined before entry to the function.
3519
* This memory could be from global variables, or from other memory that was reachable from a
3620
* pointer that was passed into the function.
3721
*/
38-
predicate functionReadsMemory(Function f) {
39-
not exists(SideEffectFunction sideEffect |
40-
sideEffect = f and not sideEffect.readsMemory()
41-
)
42-
}
22+
abstract predicate neverReadsMemory();
4323

4424
/**
45-
* Holds if the function `f` may write to memory that remains allocated after the function returns.
46-
* This memory could be from global variables, or from other memory that was reachable from a
47-
* pointer that was passed into the function.
48-
*/
49-
predicate functionWritesMemory(Function f) {
50-
not exists(SideEffectFunction sideEffect |
51-
sideEffect = f and not sideEffect.writesMemory()
52-
)
53-
}
25+
* Holds if the function never writes to memory that remains allocated after the function
26+
* returns. This memory could be from global variables, or from other memory that was reachable
27+
* from a pointer that was passed into the function.
28+
*/
29+
abstract predicate neverWritesMemory();
5430
}

0 commit comments

Comments
 (0)