mirror of
https://github.com/github/codeql.git
synced 2026-07-06 12:05:31 +02:00
Compare commits
333 Commits
codeql-cli
...
aeisenberg
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d79b207eb1 | ||
|
|
c23938d119 | ||
|
|
1a697fe993 | ||
|
|
3ccdce291a | ||
|
|
62adb31ca6 | ||
|
|
9d866192a6 | ||
|
|
e051815d96 | ||
|
|
8325c4c69c | ||
|
|
cbe54717f6 | ||
|
|
776c01aa8d | ||
|
|
90272ddbfa | ||
|
|
d5dc95f1e6 | ||
|
|
377301a55a | ||
|
|
97c9207595 | ||
|
|
251036c6b4 | ||
|
|
f9f57e9122 | ||
|
|
20672acb74 | ||
|
|
06a4f907ef | ||
|
|
6280ed2a6b | ||
|
|
c172b946a1 | ||
|
|
4aea4c0323 | ||
|
|
c04428dedc | ||
|
|
9724516c84 | ||
|
|
af06763c42 | ||
|
|
4fb29c4473 | ||
|
|
61eda0df9d | ||
|
|
05b0a3f41c | ||
|
|
fe575df325 | ||
|
|
4e62dc81d2 | ||
|
|
123dcc75d1 | ||
|
|
9bd00c9e1e | ||
|
|
2a6ad00a2f | ||
|
|
72e7b6c872 | ||
|
|
01c6dbaa27 | ||
|
|
8901b1fd14 | ||
|
|
59e22f6cd9 | ||
|
|
e4cd29efc6 | ||
|
|
d75da82528 | ||
|
|
f953249692 | ||
|
|
de47838c36 | ||
|
|
f8e8b362ab | ||
|
|
3ece3ec50f | ||
|
|
1ce15ae2fd | ||
|
|
d0c2b4a60f | ||
|
|
bae0ea5599 | ||
|
|
fa6d61809e | ||
|
|
d04dc9afe0 | ||
|
|
f986484813 | ||
|
|
674a5bb9b4 | ||
|
|
2db07bdbf3 | ||
|
|
40eef25133 | ||
|
|
591b1b4f07 | ||
|
|
81f3609c4b | ||
|
|
dfc51922ba | ||
|
|
ef2b225144 | ||
|
|
1cb5f35c56 | ||
|
|
cd0af0fc57 | ||
|
|
050dcb1370 | ||
|
|
f796efe470 | ||
|
|
9741ddb926 | ||
|
|
31f68d2da8 | ||
|
|
2c8f3a58b3 | ||
|
|
44b6309e07 | ||
|
|
e259b25428 | ||
|
|
0704946324 | ||
|
|
bdff0fdcc5 | ||
|
|
0d71072f94 | ||
|
|
6d8a83fc1f | ||
|
|
0d469536ae | ||
|
|
ef0370b64e | ||
|
|
a8236e1545 | ||
|
|
ffeb86c1f5 | ||
|
|
5455a365d1 | ||
|
|
5073f4f7dd | ||
|
|
9662950405 | ||
|
|
bfd2e4350b | ||
|
|
afc0d0a078 | ||
|
|
5c8f21d596 | ||
|
|
94f290411f | ||
|
|
1347f55d89 | ||
|
|
42ee501b96 | ||
|
|
f932e515a7 | ||
|
|
68a972d578 | ||
|
|
6b37cb0718 | ||
|
|
da5250d3a7 | ||
|
|
8edf19adc0 | ||
|
|
ff788c93c0 | ||
|
|
9cb01d4573 | ||
|
|
d39609254c | ||
|
|
c989e01197 | ||
|
|
4dc1a10f71 | ||
|
|
e226da4f04 | ||
|
|
46b92f372b | ||
|
|
2396c3c798 | ||
|
|
1530037eae | ||
|
|
9dff666cb3 | ||
|
|
58689c90fb | ||
|
|
0a7772d8a7 | ||
|
|
d23d138e7d | ||
|
|
bab89c46b6 | ||
|
|
0a382bf0cf | ||
|
|
c70d39539e | ||
|
|
f307f272d5 | ||
|
|
6960c5232b | ||
|
|
c8749ff82e | ||
|
|
209fa1a10a | ||
|
|
0593eaad52 | ||
|
|
cc752113af | ||
|
|
7689db7d42 | ||
|
|
1b97804f45 | ||
|
|
e1329dff72 | ||
|
|
b6aea3cde1 | ||
|
|
d189526283 | ||
|
|
707acdef08 | ||
|
|
450137d2cf | ||
|
|
0ba5a74f6a | ||
|
|
a05266c236 | ||
|
|
ff9093f2de | ||
|
|
358a1b3a20 | ||
|
|
6d1c00742f | ||
|
|
221c18934c | ||
|
|
8eb3b31ee2 | ||
|
|
72e05c952e | ||
|
|
c0263bef5a | ||
|
|
6b68cf6bdc | ||
|
|
06a3bf8808 | ||
|
|
822f8b06f0 | ||
|
|
a944922c97 | ||
|
|
b34b589005 | ||
|
|
c051d33cc7 | ||
|
|
ebeb187fd9 | ||
|
|
52020f7e5b | ||
|
|
91edf82c8a | ||
|
|
b640bdccdc | ||
|
|
52f8f04e9d | ||
|
|
91f5f086fb | ||
|
|
d2f5734ac5 | ||
|
|
9d6260b334 | ||
|
|
30abc958a8 | ||
|
|
eea3e82cca | ||
|
|
27314aac16 | ||
|
|
1aa63c3f2e | ||
|
|
9d75782c44 | ||
|
|
087b0dac1d | ||
|
|
9fb657c4c4 | ||
|
|
4d3377b116 | ||
|
|
3e7a60c1a6 | ||
|
|
c693f03462 | ||
|
|
245f43dd58 | ||
|
|
a6cb511ed7 | ||
|
|
f3069c8fbb | ||
|
|
78b66abad3 | ||
|
|
93c9910e6f | ||
|
|
f7d681516a | ||
|
|
225d2915e5 | ||
|
|
e4b9335ce0 | ||
|
|
099c282277 | ||
|
|
7a48fe1102 | ||
|
|
c5da43e691 | ||
|
|
34ad211900 | ||
|
|
032ae9e1e7 | ||
|
|
8e7e7c0188 | ||
|
|
9478139390 | ||
|
|
5a1adc51c1 | ||
|
|
a35be08d18 | ||
|
|
5a39610ba7 | ||
|
|
5854e88f63 | ||
|
|
d77d7c533b | ||
|
|
ecefa3e383 | ||
|
|
3f5b4a81cf | ||
|
|
44e33c7be7 | ||
|
|
d8cc92068a | ||
|
|
4a34dc125b | ||
|
|
b3bffb6826 | ||
|
|
7ec3162583 | ||
|
|
a5efe9fa09 | ||
|
|
90b25a6696 | ||
|
|
5e484e4006 | ||
|
|
b1bea31720 | ||
|
|
28cff2ea20 | ||
|
|
1de91b4cd5 | ||
|
|
ff60d9647f | ||
|
|
ec134927d8 | ||
|
|
9f79a39deb | ||
|
|
854a277ab5 | ||
|
|
b7542ee575 | ||
|
|
eaf2949857 | ||
|
|
741a3289a1 | ||
|
|
4cbc3349f6 | ||
|
|
acbca9c108 | ||
|
|
3edeb82d5b | ||
|
|
89f958105a | ||
|
|
1456012b54 | ||
|
|
4920039a00 | ||
|
|
a98fac0d7d | ||
|
|
6026f65f8b | ||
|
|
43df4a9393 | ||
|
|
c3f2faff76 | ||
|
|
a9f6b2110e | ||
|
|
4c8da54b64 | ||
|
|
67dac96e80 | ||
|
|
e467cc033e | ||
|
|
1ed5af1d6a | ||
|
|
db53be39fe | ||
|
|
37ceb0118a | ||
|
|
e461691c85 | ||
|
|
5e6c9fb661 | ||
|
|
5a5c5d1012 | ||
|
|
29bda5a805 | ||
|
|
c1bd892a13 | ||
|
|
4f80ae2190 | ||
|
|
092de640fe | ||
|
|
ff8bb2b1f8 | ||
|
|
d2573310c6 | ||
|
|
b5b9c4d931 | ||
|
|
bb86a07a93 | ||
|
|
5912a17ab4 | ||
|
|
49cc8f8ff8 | ||
|
|
8038796207 | ||
|
|
3defc8b5de | ||
|
|
437c679266 | ||
|
|
af562f15f3 | ||
|
|
e8718f9d2f | ||
|
|
7b03f3268f | ||
|
|
06a9599906 | ||
|
|
11f5663afc | ||
|
|
a0954f15c0 | ||
|
|
45e92cec6a | ||
|
|
2ad70cbee2 | ||
|
|
db9cd1f612 | ||
|
|
b1608d815b | ||
|
|
b4fa23d731 | ||
|
|
c256c87a7e | ||
|
|
281212a22c | ||
|
|
999fb07931 | ||
|
|
8262330e4d | ||
|
|
b00e312569 | ||
|
|
f931dab14a | ||
|
|
ffc61ae1bb | ||
|
|
6d468c1bae | ||
|
|
4790656b79 | ||
|
|
2a5144d9d9 | ||
|
|
a64eafca2b | ||
|
|
d6d2a213e7 | ||
|
|
f3e5b55cc4 | ||
|
|
661a4126ac | ||
|
|
baf51334e4 | ||
|
|
ad4bca9975 | ||
|
|
0990a370c7 | ||
|
|
9713551448 | ||
|
|
4fa45bb81c | ||
|
|
62944ee473 | ||
|
|
3bd330423d | ||
|
|
9a66e66d66 | ||
|
|
7bb7d83b26 | ||
|
|
aef0a03ab6 | ||
|
|
94078e851c | ||
|
|
7b8301ac7a | ||
|
|
1c8e0c453c | ||
|
|
5f70c44270 | ||
|
|
9dd43d8e6f | ||
|
|
070d67816d | ||
|
|
8d93c3a852 | ||
|
|
e885f1f8c4 | ||
|
|
983bdb92a1 | ||
|
|
123214cb2b | ||
|
|
d8e2d355df | ||
|
|
025aa77e79 | ||
|
|
8c106964ec | ||
|
|
3868b386f3 | ||
|
|
0165696a1e | ||
|
|
8ba48e801a | ||
|
|
dd3cc33298 | ||
|
|
c824aa4e45 | ||
|
|
a3b5d2a28d | ||
|
|
4fbf76008e | ||
|
|
efcd4e297e | ||
|
|
db8a5306cf | ||
|
|
eed8b3e87b | ||
|
|
dd4bce8e30 | ||
|
|
7a5838f1a2 | ||
|
|
e87d2fe922 | ||
|
|
d4bfab4735 | ||
|
|
b83147fa44 | ||
|
|
8241d0b7ef | ||
|
|
07a25a233d | ||
|
|
64432215a9 | ||
|
|
8526510783 | ||
|
|
173cd13ded | ||
|
|
fe1103d997 | ||
|
|
7df59ffe6c | ||
|
|
a6833945c1 | ||
|
|
d31711bd89 | ||
|
|
f1324a413a | ||
|
|
60b9d19d72 | ||
|
|
8458bde51e | ||
|
|
9e25279cb8 | ||
|
|
162245fb9a | ||
|
|
059ef42f41 | ||
|
|
878867205e | ||
|
|
91db2b6c9c | ||
|
|
51f3f15e42 | ||
|
|
d79a253c20 | ||
|
|
7380e29774 | ||
|
|
d994959720 | ||
|
|
81ec6861f9 | ||
|
|
f217de9623 | ||
|
|
6a46fb54c5 | ||
|
|
f017821062 | ||
|
|
d4203d9286 | ||
|
|
02b0b402d6 | ||
|
|
484923e706 | ||
|
|
be03e582c6 | ||
|
|
9fffd7846a | ||
|
|
c9daf914cb | ||
|
|
3eb5778543 | ||
|
|
e23cbeda24 | ||
|
|
4b68dd2315 | ||
|
|
9946e07f36 | ||
|
|
59fb479895 | ||
|
|
e34cc42441 | ||
|
|
7fcf39277d | ||
|
|
863fa364e2 | ||
|
|
bb8063c0f4 | ||
|
|
2ab10262fc | ||
|
|
83cffea1a1 | ||
|
|
3e9c3e6987 | ||
|
|
c1b9310ec2 | ||
|
|
9877294b1c | ||
|
|
193693565c | ||
|
|
45499b03d2 | ||
|
|
21b5571bff | ||
|
|
7354db873a |
2296
cpp/downgrades/25e365d1e8147df0f759b604f96eb4bffea48271/old.dbscheme
Normal file
2296
cpp/downgrades/25e365d1e8147df0f759b604f96eb4bffea48271/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
|||||||
|
description: Revert support for using-enum declarations.
|
||||||
|
compatibility: partial
|
||||||
|
usings.rel: run usings.qlo
|
||||||
|
using_container.rel: run using_container.qlo
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
class UsingEntry extends @using {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Element extends @element {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
from UsingEntry u, Element parent, int kind
|
||||||
|
where
|
||||||
|
usings(u, _, _, kind) and
|
||||||
|
using_container(parent, u) and
|
||||||
|
kind != 3
|
||||||
|
select parent, u
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class UsingEntry extends @using {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Element extends @element {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Location extends @location_default {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
from UsingEntry u, Element target, Location loc, int kind
|
||||||
|
where
|
||||||
|
usings(u, target, loc, kind) and
|
||||||
|
kind != 3
|
||||||
|
select u, target, loc
|
||||||
2300
cpp/downgrades/9629fc87dab7dbed0771bf5ce22bce4d7f943b52/old.dbscheme
Normal file
2300
cpp/downgrades/9629fc87dab7dbed0771bf5ce22bce4d7f943b52/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
|||||||
|
description: Support destroying deletes
|
||||||
|
compatibility: full
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: feature
|
||||||
|
---
|
||||||
|
* A `isDestroyingDeleteDeallocation` predicate was added to the `NewOrNewArrayExpr` and `DeleteOrDeleteArrayExpr` classes to indicate whether the deallocation function is a destroying delete.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* A `UsingEnumDeclarationEntry` class has been added for C++ `using enum` declarations. As part of this, synthesized `UsingDeclarationEntry`s are no longer emitted for individual enumerators of the referenced enumeration.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* Improved performance of alias analysis of large function bodies. In rare cases, alerts that depend on alias analysis of large function bodies may be affected.
|
||||||
4
cpp/ql/lib/change-notes/2024-07-31-constexpr-if.md
Normal file
4
cpp/ql/lib/change-notes/2024-07-31-constexpr-if.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* The controlling expression of a `constexpr if` is now always recognized as an unevaluated expression.
|
||||||
14
cpp/ql/lib/ext/std.format.model.yml
Normal file
14
cpp/ql/lib/ext/std.format.model.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
extensions:
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/cpp-all
|
||||||
|
extensible: summaryModel
|
||||||
|
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||||
|
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||||
|
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*1]", "ReturnValue", "taint", "manual"]
|
||||||
|
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*2]", "ReturnValue", "taint", "manual"]
|
||||||
|
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*3]", "ReturnValue", "taint", "manual"]
|
||||||
|
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*4]", "ReturnValue", "taint", "manual"]
|
||||||
|
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*5]", "ReturnValue", "taint", "manual"]
|
||||||
|
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*6]", "ReturnValue", "taint", "manual"]
|
||||||
|
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*7]", "ReturnValue", "taint", "manual"]
|
||||||
|
- ["std", "", False, "format<Args>", "(format_string,Args &&)", "", "Argument[*8]", "ReturnValue", "taint", "manual"]
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/cpp-all
|
name: codeql/cpp-all
|
||||||
version: 1.3.0
|
version: 1.3.1-dev
|
||||||
groups: cpp
|
groups: cpp
|
||||||
dbscheme: semmlecode.cpp.dbscheme
|
dbscheme: semmlecode.cpp.dbscheme
|
||||||
extractor: cpp
|
extractor: cpp
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ class NamespaceDeclarationEntry extends Locatable, @namespace_decl {
|
|||||||
* A C++ `using` directive or `using` declaration.
|
* A C++ `using` directive or `using` declaration.
|
||||||
*/
|
*/
|
||||||
class UsingEntry extends Locatable, @using {
|
class UsingEntry extends Locatable, @using {
|
||||||
override Location getLocation() { usings(underlyingElement(this), _, result) }
|
override Location getLocation() { usings(underlyingElement(this), _, result, _) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,15 +166,13 @@ class UsingEntry extends Locatable, @using {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class UsingDeclarationEntry extends UsingEntry {
|
class UsingDeclarationEntry extends UsingEntry {
|
||||||
UsingDeclarationEntry() {
|
UsingDeclarationEntry() { usings(underlyingElement(this), _, _, 1) }
|
||||||
not exists(Namespace n | usings(underlyingElement(this), unresolveElement(n), _))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the declaration that is referenced by this using declaration. For
|
* Gets the declaration that is referenced by this using declaration. For
|
||||||
* example, `std::string` in `using std::string`.
|
* example, `std::string` in `using std::string`.
|
||||||
*/
|
*/
|
||||||
Declaration getDeclaration() { usings(underlyingElement(this), unresolveElement(result), _) }
|
Declaration getDeclaration() { usings(underlyingElement(this), unresolveElement(result), _, _) }
|
||||||
|
|
||||||
override string toString() { result = "using " + this.getDeclaration().getDescription() }
|
override string toString() { result = "using " + this.getDeclaration().getDescription() }
|
||||||
}
|
}
|
||||||
@@ -186,19 +184,36 @@ class UsingDeclarationEntry extends UsingEntry {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class UsingDirectiveEntry extends UsingEntry {
|
class UsingDirectiveEntry extends UsingEntry {
|
||||||
UsingDirectiveEntry() {
|
UsingDirectiveEntry() { usings(underlyingElement(this), _, _, 2) }
|
||||||
exists(Namespace n | usings(underlyingElement(this), unresolveElement(n), _))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the namespace that is referenced by this using directive. For
|
* Gets the namespace that is referenced by this using directive. For
|
||||||
* example, `std` in `using namespace std`.
|
* example, `std` in `using namespace std`.
|
||||||
*/
|
*/
|
||||||
Namespace getNamespace() { usings(underlyingElement(this), unresolveElement(result), _) }
|
Namespace getNamespace() { usings(underlyingElement(this), unresolveElement(result), _, _) }
|
||||||
|
|
||||||
override string toString() { result = "using namespace " + this.getNamespace().getFriendlyName() }
|
override string toString() { result = "using namespace " + this.getNamespace().getFriendlyName() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A C++ `using enum` declaration. For example:
|
||||||
|
* ```
|
||||||
|
* enum class Foo { a, b };
|
||||||
|
* using enum Foo;
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class UsingEnumDeclarationEntry extends UsingEntry {
|
||||||
|
UsingEnumDeclarationEntry() { usings(underlyingElement(this), _, _, 3) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the enumeration that is referenced by this using directive. For
|
||||||
|
* example, `Foo` in `using enum Foo`.
|
||||||
|
*/
|
||||||
|
Enum getEnum() { usings(underlyingElement(this), unresolveElement(result), _, _) }
|
||||||
|
|
||||||
|
override string toString() { result = "using enum " + this.getEnum().getQualifiedName() }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `g` is an instance of `GlobalNamespace`. This predicate
|
* Holds if `g` is an instance of `GlobalNamespace`. This predicate
|
||||||
* is used suppress a warning in `GlobalNamespace.getADeclaration()`
|
* is used suppress a warning in `GlobalNamespace.getADeclaration()`
|
||||||
|
|||||||
@@ -435,12 +435,17 @@ private predicate elementSpec(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the fully templated version of `f`. */
|
/** Gets the fully templated version of `f`. */
|
||||||
private Function getFullyTemplatedMemberFunction(Function f) {
|
private Function getFullyTemplatedFunction(Function f) {
|
||||||
not f.isFromUninstantiatedTemplate(_) and
|
not f.isFromUninstantiatedTemplate(_) and
|
||||||
exists(Class c, Class templateClass, int i |
|
(
|
||||||
c.isConstructedFrom(templateClass) and
|
exists(Class c, Class templateClass, int i |
|
||||||
f = c.getAMember(i) and
|
c.isConstructedFrom(templateClass) and
|
||||||
result = templateClass.getCanonicalMember(i)
|
f = c.getAMember(i) and
|
||||||
|
result = templateClass.getCanonicalMember(i)
|
||||||
|
)
|
||||||
|
or
|
||||||
|
not exists(f.getDeclaringType()) and
|
||||||
|
f.isConstructedFrom(result)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,14 +469,14 @@ string getParameterTypeWithoutTemplateArguments(Function f, int n) {
|
|||||||
*/
|
*/
|
||||||
private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) {
|
private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) {
|
||||||
exists(Function templateFunction |
|
exists(Function templateFunction |
|
||||||
templateFunction = getFullyTemplatedMemberFunction(f) and
|
templateFunction = getFullyTemplatedFunction(f) and
|
||||||
remaining = templateFunction.getNumberOfTemplateArguments() and
|
remaining = templateFunction.getNumberOfTemplateArguments() and
|
||||||
result = getParameterTypeWithoutTemplateArguments(templateFunction, n)
|
result = getParameterTypeWithoutTemplateArguments(templateFunction, n)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(string mid, TemplateParameter tp, Function templateFunction |
|
exists(string mid, TemplateParameter tp, Function templateFunction |
|
||||||
mid = getTypeNameWithoutFunctionTemplates(f, n, remaining + 1) and
|
mid = getTypeNameWithoutFunctionTemplates(f, n, remaining + 1) and
|
||||||
templateFunction = getFullyTemplatedMemberFunction(f) and
|
templateFunction = getFullyTemplatedFunction(f) and
|
||||||
tp = templateFunction.getTemplateArgument(remaining) and
|
tp = templateFunction.getTemplateArgument(remaining) and
|
||||||
result = mid.replaceAll(tp.getName(), "func:" + remaining.toString())
|
result = mid.replaceAll(tp.getName(), "func:" + remaining.toString())
|
||||||
)
|
)
|
||||||
@@ -482,12 +487,18 @@ private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remain
|
|||||||
* with `class:N` (where `N` is the index of the template).
|
* with `class:N` (where `N` is the index of the template).
|
||||||
*/
|
*/
|
||||||
private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) {
|
private string getTypeNameWithoutClassTemplates(Function f, int n, int remaining) {
|
||||||
|
// If there is a declaring type then we start by expanding the function templates
|
||||||
exists(Class template |
|
exists(Class template |
|
||||||
f.getDeclaringType().isConstructedFrom(template) and
|
f.getDeclaringType().isConstructedFrom(template) and
|
||||||
remaining = template.getNumberOfTemplateArguments() and
|
remaining = template.getNumberOfTemplateArguments() and
|
||||||
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
|
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
|
// If there is no declaring type we're done after expanding the function templates
|
||||||
|
not exists(f.getDeclaringType()) and
|
||||||
|
remaining = 0 and
|
||||||
|
result = getTypeNameWithoutFunctionTemplates(f, n, 0)
|
||||||
|
or
|
||||||
exists(string mid, TemplateParameter tp, Class template |
|
exists(string mid, TemplateParameter tp, Class template |
|
||||||
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
|
mid = getTypeNameWithoutClassTemplates(f, n, remaining + 1) and
|
||||||
f.getDeclaringType().isConstructedFrom(template) and
|
f.getDeclaringType().isConstructedFrom(template) and
|
||||||
@@ -570,38 +581,6 @@ private string getSignatureWithoutFunctionTemplateNames(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private string paramsStringPart(Function c, int i) {
|
|
||||||
not c.isFromUninstantiatedTemplate(_) and
|
|
||||||
(
|
|
||||||
i = -1 and result = "(" and exists(c)
|
|
||||||
or
|
|
||||||
exists(int n, string p | getParameterTypeName(c, n) = p |
|
|
||||||
i = 2 * n and result = p
|
|
||||||
or
|
|
||||||
i = 2 * n - 1 and result = "," and n != 0
|
|
||||||
)
|
|
||||||
or
|
|
||||||
i = 2 * c.getNumberOfParameters() and result = ")"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a parenthesized string containing all parameter types of this callable, separated by a comma.
|
|
||||||
*
|
|
||||||
* Returns the empty string if the callable has no parameters.
|
|
||||||
* Parameter types are represented by their type erasure.
|
|
||||||
*/
|
|
||||||
cached
|
|
||||||
private string paramsString(Function c) {
|
|
||||||
result = concat(int i | | paramsStringPart(c, i) order by i)
|
|
||||||
}
|
|
||||||
|
|
||||||
bindingset[func]
|
|
||||||
private predicate matchesSignature(Function func, string signature) {
|
|
||||||
signature = "" or
|
|
||||||
paramsString(func) = signature
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `elementSpec(_, type, _, name, signature, _)` holds and
|
* Holds if `elementSpec(_, type, _, name, signature, _)` holds and
|
||||||
* - `typeArgs` represents the named template parameters supplied to `type`, and
|
* - `typeArgs` represents the named template parameters supplied to `type`, and
|
||||||
@@ -750,17 +729,17 @@ private predicate elementSpecWithArguments0(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `elementSpec(namespace, type, subtypes, name, signature, _)` and
|
* Holds if `elementSpec(namespace, type, subtypes, name, signature, _)` and
|
||||||
* `method`'s signature matches `signature`.
|
* `func`'s signature matches `signature`.
|
||||||
*
|
*
|
||||||
* `signature` may contain template parameter names that are bound by `type` and `name`.
|
* `signature` may contain template parameter names that are bound by `type` and `name`.
|
||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate elementSpecMatchesSignature(
|
private predicate elementSpecMatchesSignature(
|
||||||
Function method, string namespace, string type, boolean subtypes, string name, string signature
|
Function func, string namespace, string type, boolean subtypes, string name, string signature
|
||||||
) {
|
) {
|
||||||
elementSpec(namespace, pragma[only_bind_into](type), subtypes, pragma[only_bind_into](name),
|
elementSpec(namespace, pragma[only_bind_into](type), subtypes, pragma[only_bind_into](name),
|
||||||
pragma[only_bind_into](signature), _) and
|
pragma[only_bind_into](signature), _) and
|
||||||
signatureMatches(method, signature, type, name, 0)
|
signatureMatches(func, signature, type, name, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -776,13 +755,22 @@ private predicate hasClassAndName(Class classWithMethod, Function method, string
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[name]
|
||||||
|
pragma[inline_late]
|
||||||
|
private predicate funcHasQualifiedName(Function func, string namespace, string name) {
|
||||||
|
exists(string nameWithoutArgs |
|
||||||
|
parseAngles(name, nameWithoutArgs, _, "") and
|
||||||
|
func.hasQualifiedName(namespace, nameWithoutArgs)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `namedClass` is in namespace `namespace` and has
|
* Holds if `namedClass` is in namespace `namespace` and has
|
||||||
* name `type` (excluding any template parameters).
|
* name `type` (excluding any template parameters).
|
||||||
*/
|
*/
|
||||||
bindingset[type, namespace]
|
bindingset[type, namespace]
|
||||||
pragma[inline_late]
|
pragma[inline_late]
|
||||||
private predicate hasQualifiedName(Class namedClass, string namespace, string type) {
|
private predicate classHasQualifiedName(Class namedClass, string namespace, string type) {
|
||||||
exists(string typeWithoutArgs |
|
exists(string typeWithoutArgs |
|
||||||
parseAngles(type, typeWithoutArgs, _, "") and
|
parseAngles(type, typeWithoutArgs, _, "") and
|
||||||
namedClass.hasQualifiedName(namespace, typeWithoutArgs)
|
namedClass.hasQualifiedName(namespace, typeWithoutArgs)
|
||||||
@@ -804,15 +792,16 @@ private Element interpretElement0(
|
|||||||
string namespace, string type, boolean subtypes, string name, string signature
|
string namespace, string type, boolean subtypes, string name, string signature
|
||||||
) {
|
) {
|
||||||
(
|
(
|
||||||
elementSpec(namespace, type, subtypes, name, signature, _) and
|
|
||||||
// Non-member functions
|
// Non-member functions
|
||||||
exists(Function func |
|
elementSpec(namespace, type, subtypes, name, signature, _) and
|
||||||
func.hasQualifiedName(namespace, name) and
|
subtypes = false and
|
||||||
type = "" and
|
type = "" and
|
||||||
matchesSignature(func, signature) and
|
(
|
||||||
subtypes = false and
|
elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature)
|
||||||
not exists(func.getDeclaringType()) and
|
or
|
||||||
result = func
|
signature = "" and
|
||||||
|
elementSpec(namespace, type, subtypes, name, "", _) and
|
||||||
|
funcHasQualifiedName(result, namespace, name)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Member functions
|
// Member functions
|
||||||
@@ -825,7 +814,7 @@ private Element interpretElement0(
|
|||||||
elementSpec(namespace, type, subtypes, name, "", _) and
|
elementSpec(namespace, type, subtypes, name, "", _) and
|
||||||
hasClassAndName(classWithMethod, result, name)
|
hasClassAndName(classWithMethod, result, name)
|
||||||
) and
|
) and
|
||||||
hasQualifiedName(namedClass, namespace, type) and
|
classHasQualifiedName(namedClass, namespace, type) and
|
||||||
(
|
(
|
||||||
// member declared in the named type or a subtype of it
|
// member declared in the named type or a subtype of it
|
||||||
subtypes = true and
|
subtypes = true and
|
||||||
|
|||||||
@@ -215,19 +215,16 @@ predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
|
|||||||
predicate localMustFlowStep(Node node1, Node node2) { none() }
|
predicate localMustFlowStep(Node node1, Node node2) { none() }
|
||||||
|
|
||||||
/** Gets the type of `n` used for type pruning. */
|
/** Gets the type of `n` used for type pruning. */
|
||||||
Type getNodeType(Node n) {
|
DataFlowType getNodeType(Node n) {
|
||||||
exists(n) and
|
exists(n) and
|
||||||
result instanceof VoidType // stub implementation
|
result instanceof VoidType // stub implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a string representation of a type returned by `getNodeType`. */
|
|
||||||
string ppReprType(Type t) { none() } // stub implementation
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
|
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
|
||||||
* a node of type `t1` to a node of type `t2`.
|
* a node of type `t1` to a node of type `t2`.
|
||||||
*/
|
*/
|
||||||
predicate compatibleTypes(Type t1, Type t2) {
|
predicate compatibleTypes(DataFlowType t1, DataFlowType t2) {
|
||||||
t1 instanceof VoidType and t2 instanceof VoidType // stub implementation
|
t1 instanceof VoidType and t2 instanceof VoidType // stub implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +240,11 @@ class DataFlowCallable extends Function { }
|
|||||||
|
|
||||||
class DataFlowExpr = Expr;
|
class DataFlowExpr = Expr;
|
||||||
|
|
||||||
class DataFlowType = Type;
|
final private class TypeFinal = Type;
|
||||||
|
|
||||||
|
class DataFlowType extends TypeFinal {
|
||||||
|
string toString() { result = "" }
|
||||||
|
}
|
||||||
|
|
||||||
/** A function call relevant for data flow. */
|
/** A function call relevant for data flow. */
|
||||||
class DataFlowCall extends Expr instanceof Call {
|
class DataFlowCall extends Expr instanceof Call {
|
||||||
|
|||||||
@@ -307,6 +307,10 @@ class Expr extends StmtParent, @expr {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(Decltype d | d.getExpr() = this.getParentWithConversions*())
|
exists(Decltype d | d.getExpr() = this.getParentWithConversions*())
|
||||||
|
or
|
||||||
|
exists(ConstexprIfStmt constIf |
|
||||||
|
constIf.getControllingExpr() = this.getParentWithConversions*()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -855,6 +859,16 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if the deallocation function is a destroying delete.
|
||||||
|
*/
|
||||||
|
predicate isDestroyingDeleteDeallocation() {
|
||||||
|
exists(int form |
|
||||||
|
expr_deallocator(underlyingElement(this), _, form) and
|
||||||
|
form.bitAnd(4) != 0 // Bit two is the "destroying delete" bit
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the type that is being allocated.
|
* Gets the type that is being allocated.
|
||||||
*
|
*
|
||||||
@@ -1025,6 +1039,16 @@ class DeleteOrDeleteArrayExpr extends Expr, TDeleteOrDeleteArrayExpr {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if the deallocation function is a destroying delete.
|
||||||
|
*/
|
||||||
|
predicate isDestroyingDeleteDeallocation() {
|
||||||
|
exists(int form |
|
||||||
|
expr_deallocator(underlyingElement(this), _, form) and
|
||||||
|
form.bitAnd(4) != 0 // Bit two is the "destroying delete" bit
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the object or array being deleted.
|
* Gets the object or array being deleted.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -994,9 +994,6 @@ DataFlowType getNodeType(Node n) {
|
|||||||
result instanceof VoidType // stub implementation
|
result instanceof VoidType // stub implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a string representation of a type returned by `getNodeType`. */
|
|
||||||
string ppReprType(DataFlowType t) { none() } // stub implementation
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
|
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
|
||||||
* a node of type `t1` to a node of type `t2`.
|
* a node of type `t1` to a node of type `t2`.
|
||||||
@@ -1097,7 +1094,11 @@ class SummarizedCallable extends DataFlowCallable, TSummarizedCallable {
|
|||||||
|
|
||||||
class DataFlowExpr = Expr;
|
class DataFlowExpr = Expr;
|
||||||
|
|
||||||
class DataFlowType = Type;
|
final private class TypeFinal = Type;
|
||||||
|
|
||||||
|
class DataFlowType extends TypeFinal {
|
||||||
|
string toString() { result = "" }
|
||||||
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
private newtype TDataFlowCall =
|
private newtype TDataFlowCall =
|
||||||
|
|||||||
@@ -338,6 +338,56 @@ private predicate resultEscapesNonReturn(Instruction instr) {
|
|||||||
not instr.isResultModeled()
|
not instr.isResultModeled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Holds if `operand` may (transitively) flow to an `AddressOperand`. */
|
||||||
|
private predicate consumedAsAddressOperand(Operand operand) {
|
||||||
|
operand instanceof AddressOperand
|
||||||
|
or
|
||||||
|
exists(Operand address |
|
||||||
|
consumedAsAddressOperand(address) and
|
||||||
|
operandIsPropagated(operand, _, address.getDef())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `operand` may originate from a base instruction of an allocation,
|
||||||
|
* and that operand may transitively flow to an `AddressOperand`.
|
||||||
|
*/
|
||||||
|
private predicate propagatedFromAllocationBase(Operand operand, Configuration::Allocation allocation) {
|
||||||
|
consumedAsAddressOperand(operand) and
|
||||||
|
(
|
||||||
|
not exists(Configuration::getOldAllocation(allocation)) and
|
||||||
|
operand.getDef() = allocation.getABaseInstruction()
|
||||||
|
or
|
||||||
|
exists(Operand address |
|
||||||
|
operandIsPropagated(address, _, operand.getDef()) and
|
||||||
|
propagatedFromAllocationBase(address, allocation)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private predicate propagatedFromNonAllocationBase(Operand operand) {
|
||||||
|
exists(Instruction def |
|
||||||
|
def = operand.getDef() and
|
||||||
|
not operandIsPropagated(_, _, def) and
|
||||||
|
not def = any(Configuration::Allocation allocation).getABaseInstruction()
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(Operand address |
|
||||||
|
operandIsPropagated(address, _, operand.getDef()) and
|
||||||
|
propagatedFromNonAllocationBase(address)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if we cannot see all producers of an operand for which allocation also flows into.
|
||||||
|
*/
|
||||||
|
private predicate operandConsumesEscaped(Configuration::Allocation allocation) {
|
||||||
|
exists(AddressOperand address |
|
||||||
|
propagatedFromAllocationBase(address, allocation) and
|
||||||
|
propagatedFromNonAllocationBase(address)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the address of `allocation` escapes outside the domain of the analysis. This can occur
|
* Holds if the address of `allocation` escapes outside the domain of the analysis. This can occur
|
||||||
* either because the allocation's address is taken within the function and escapes, or because the
|
* either because the allocation's address is taken within the function and escapes, or because the
|
||||||
@@ -346,12 +396,14 @@ private predicate resultEscapesNonReturn(Instruction instr) {
|
|||||||
predicate allocationEscapes(Configuration::Allocation allocation) {
|
predicate allocationEscapes(Configuration::Allocation allocation) {
|
||||||
allocation.alwaysEscapes()
|
allocation.alwaysEscapes()
|
||||||
or
|
or
|
||||||
exists(IREscapeAnalysisConfiguration config |
|
exists(IREscapeAnalysisConfiguration config | config.useSoundEscapeAnalysis() |
|
||||||
config.useSoundEscapeAnalysis() and resultEscapesNonReturn(allocation.getABaseInstruction())
|
resultEscapesNonReturn(allocation.getABaseInstruction())
|
||||||
|
or
|
||||||
|
operandConsumesEscaped(allocation)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
Configuration::phaseNeedsSoundEscapeAnalysis() and
|
Configuration::phaseNeedsSoundEscapeAnalysis() and
|
||||||
resultEscapesNonReturn(allocation.getABaseInstruction())
|
(resultEscapesNonReturn(allocation.getABaseInstruction()) or operandConsumesEscaped(allocation))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -146,3 +146,8 @@ class DynamicAllocation extends Allocation, TDynamicAllocation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
predicate phaseNeedsSoundEscapeAnalysis() { none() }
|
predicate phaseNeedsSoundEscapeAnalysis() { none() }
|
||||||
|
|
||||||
|
UnaliasedSsa::Allocation getOldAllocation(VariableAllocation allocation) {
|
||||||
|
UnaliasedSsa::canReuseSsaForVariable(allocation.getIRVariable()) and
|
||||||
|
result = allocation.getIRVariable()
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConst
|
|||||||
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
|
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
|
||||||
private import semmle.code.cpp.ir.internal.IntegerInterval as Interval
|
private import semmle.code.cpp.ir.internal.IntegerInterval as Interval
|
||||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||||
private import AliasConfiguration
|
import AliasConfiguration
|
||||||
private import codeql.util.Boolean
|
private import codeql.util.Boolean
|
||||||
|
|
||||||
private class IntValue = Ints::IntValue;
|
private class IntValue = Ints::IntValue;
|
||||||
@@ -227,13 +227,15 @@ private newtype TMemoryLocation =
|
|||||||
TAllAliasedMemory(IRFunction irFunc, Boolean isMayAccess)
|
TAllAliasedMemory(IRFunction irFunc, Boolean isMayAccess)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the memory location accessed by a memory operand or memory result. In this implementation, the location is
|
* A memory location accessed by a memory operand or memory result. In this implementation, the location is
|
||||||
* one of the following:
|
* one of the following:
|
||||||
* - `VariableMemoryLocation` - A location within a known `IRVariable`, at an offset that is either a constant or is
|
* - `VariableMemoryLocation` - A location within a known `IRVariable`, at an offset that is either a constant or is
|
||||||
* unknown.
|
* unknown.
|
||||||
* - `UnknownMemoryLocation` - A location not known to be within a specific `IRVariable`.
|
* - `UnknownMemoryLocation` - A location not known to be within a specific `IRVariable`.
|
||||||
|
*
|
||||||
|
* Some of these memory locations will be filtered out for performance reasons before being passed to SSA construction.
|
||||||
*/
|
*/
|
||||||
abstract class MemoryLocation extends TMemoryLocation {
|
abstract private class MemoryLocation0 extends TMemoryLocation {
|
||||||
final string toString() {
|
final string toString() {
|
||||||
if this.isMayAccess()
|
if this.isMayAccess()
|
||||||
then result = "?" + this.toStringInternal()
|
then result = "?" + this.toStringInternal()
|
||||||
@@ -294,9 +296,9 @@ abstract class MemoryLocation extends TMemoryLocation {
|
|||||||
* represented by a `MemoryLocation` that totally overlaps all other
|
* represented by a `MemoryLocation` that totally overlaps all other
|
||||||
* `MemoryLocations` in the set.
|
* `MemoryLocations` in the set.
|
||||||
*/
|
*/
|
||||||
abstract class VirtualVariable extends MemoryLocation { }
|
abstract class VirtualVariable extends MemoryLocation0 { }
|
||||||
|
|
||||||
abstract class AllocationMemoryLocation extends MemoryLocation {
|
abstract class AllocationMemoryLocation extends MemoryLocation0 {
|
||||||
Allocation var;
|
Allocation var;
|
||||||
boolean isMayAccess;
|
boolean isMayAccess;
|
||||||
|
|
||||||
@@ -424,7 +426,7 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
|
|||||||
* `{a, b}` into a memory location that represents _all_ of the allocations
|
* `{a, b}` into a memory location that represents _all_ of the allocations
|
||||||
* in the set.
|
* in the set.
|
||||||
*/
|
*/
|
||||||
class GroupedMemoryLocation extends TGroupedMemoryLocation, MemoryLocation {
|
class GroupedMemoryLocation extends TGroupedMemoryLocation, MemoryLocation0 {
|
||||||
VariableGroup vg;
|
VariableGroup vg;
|
||||||
boolean isMayAccess;
|
boolean isMayAccess;
|
||||||
boolean isAll;
|
boolean isAll;
|
||||||
@@ -528,7 +530,7 @@ class GroupedVirtualVariable extends GroupedMemoryLocation, VirtualVariable {
|
|||||||
/**
|
/**
|
||||||
* An access to memory that is not known to be confined to a specific `IRVariable`.
|
* An access to memory that is not known to be confined to a specific `IRVariable`.
|
||||||
*/
|
*/
|
||||||
class UnknownMemoryLocation extends TUnknownMemoryLocation, MemoryLocation {
|
class UnknownMemoryLocation extends TUnknownMemoryLocation, MemoryLocation0 {
|
||||||
IRFunction irFunc;
|
IRFunction irFunc;
|
||||||
boolean isMayAccess;
|
boolean isMayAccess;
|
||||||
|
|
||||||
@@ -555,7 +557,7 @@ class UnknownMemoryLocation extends TUnknownMemoryLocation, MemoryLocation {
|
|||||||
* An access to memory that is not known to be confined to a specific `IRVariable`, but is known to
|
* An access to memory that is not known to be confined to a specific `IRVariable`, but is known to
|
||||||
* not access memory on the current function's stack frame.
|
* not access memory on the current function's stack frame.
|
||||||
*/
|
*/
|
||||||
class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation {
|
class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation0 {
|
||||||
IRFunction irFunc;
|
IRFunction irFunc;
|
||||||
boolean isMayAccess;
|
boolean isMayAccess;
|
||||||
|
|
||||||
@@ -589,7 +591,7 @@ class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation {
|
|||||||
/**
|
/**
|
||||||
* An access to all aliased memory.
|
* An access to all aliased memory.
|
||||||
*/
|
*/
|
||||||
class AllAliasedMemory extends TAllAliasedMemory, MemoryLocation {
|
class AllAliasedMemory extends TAllAliasedMemory, MemoryLocation0 {
|
||||||
IRFunction irFunc;
|
IRFunction irFunc;
|
||||||
boolean isMayAccess;
|
boolean isMayAccess;
|
||||||
|
|
||||||
@@ -620,7 +622,7 @@ class AliasedVirtualVariable extends AllAliasedMemory, VirtualVariable {
|
|||||||
/**
|
/**
|
||||||
* Gets the overlap relationship between the definition location `def` and the use location `use`.
|
* Gets the overlap relationship between the definition location `def` and the use location `use`.
|
||||||
*/
|
*/
|
||||||
Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
|
Overlap getOverlap(MemoryLocation0 def, MemoryLocation0 use) {
|
||||||
exists(Overlap overlap |
|
exists(Overlap overlap |
|
||||||
// Compute the overlap based only on the extent.
|
// Compute the overlap based only on the extent.
|
||||||
overlap = getExtentOverlap(def, use) and
|
overlap = getExtentOverlap(def, use) and
|
||||||
@@ -648,7 +650,7 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
|
|||||||
* based only on the set of memory locations accessed. Handling of "may" accesses and read-only
|
* based only on the set of memory locations accessed. Handling of "may" accesses and read-only
|
||||||
* locations occurs in `getOverlap()`.
|
* locations occurs in `getOverlap()`.
|
||||||
*/
|
*/
|
||||||
private Overlap getExtentOverlap(MemoryLocation def, MemoryLocation use) {
|
private Overlap getExtentOverlap(MemoryLocation0 def, MemoryLocation0 use) {
|
||||||
// The def and the use must have the same virtual variable, or no overlap is possible.
|
// The def and the use must have the same virtual variable, or no overlap is possible.
|
||||||
(
|
(
|
||||||
// AllAliasedMemory must totally overlap any location within the same virtual variable.
|
// AllAliasedMemory must totally overlap any location within the same virtual variable.
|
||||||
@@ -861,6 +863,40 @@ predicate canReuseSsaForOldResult(Instruction instr) { OldSsa::canReuseSsaForMem
|
|||||||
bindingset[result, b]
|
bindingset[result, b]
|
||||||
private boolean unbindBool(boolean b) { result != b.booleanNot() }
|
private boolean unbindBool(boolean b) { result != b.booleanNot() }
|
||||||
|
|
||||||
|
/** Gets the number of overlapping uses of `def`. */
|
||||||
|
private int numberOfOverlappingUses(MemoryLocation0 def) {
|
||||||
|
result = strictcount(MemoryLocation0 use | exists(getOverlap(def, use)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `def` is a busy definition. That is, it has a large number of
|
||||||
|
* overlapping uses.
|
||||||
|
*/
|
||||||
|
private predicate isBusyDef(MemoryLocation0 def) { numberOfOverlappingUses(def) > 1024 }
|
||||||
|
|
||||||
|
/** Holds if `use` is a use that overlaps with a busy definition. */
|
||||||
|
private predicate useOverlapWithBusyDef(MemoryLocation0 use) {
|
||||||
|
exists(MemoryLocation0 def |
|
||||||
|
exists(getOverlap(def, use)) and
|
||||||
|
isBusyDef(def)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
final private class FinalMemoryLocation = MemoryLocation0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A memory location accessed by a memory operand or memory result. In this implementation, the location is
|
||||||
|
* one of the following:
|
||||||
|
* - `VariableMemoryLocation` - A location within a known `IRVariable`, at an offset that is either a constant or is
|
||||||
|
* unknown.
|
||||||
|
* - `UnknownMemoryLocation` - A location not known to be within a specific `IRVariable`.
|
||||||
|
*
|
||||||
|
* Compared to `MemoryLocation0`, this class does not contain memory locations that represent uses of busy definitions.
|
||||||
|
*/
|
||||||
|
class MemoryLocation extends FinalMemoryLocation {
|
||||||
|
MemoryLocation() { not useOverlapWithBusyDef(this) }
|
||||||
|
}
|
||||||
|
|
||||||
MemoryLocation getResultMemoryLocation(Instruction instr) {
|
MemoryLocation getResultMemoryLocation(Instruction instr) {
|
||||||
not canReuseSsaForOldResult(instr) and
|
not canReuseSsaForOldResult(instr) and
|
||||||
exists(MemoryAccessKind kind, boolean isMayAccess |
|
exists(MemoryAccessKind kind, boolean isMayAccess |
|
||||||
@@ -905,9 +941,9 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
|
private MemoryLocation0 getOperandMemoryLocation0(MemoryOperand operand, boolean isMayAccess) {
|
||||||
not canReuseSsaForOldResult(operand.getAnyDef()) and
|
not canReuseSsaForOldResult(operand.getAnyDef()) and
|
||||||
exists(MemoryAccessKind kind, boolean isMayAccess |
|
exists(MemoryAccessKind kind |
|
||||||
kind = operand.getMemoryAccess() and
|
kind = operand.getMemoryAccess() and
|
||||||
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
|
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
|
||||||
(
|
(
|
||||||
@@ -948,6 +984,19 @@ MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
|
||||||
|
exists(MemoryLocation0 use0, boolean isMayAccess |
|
||||||
|
use0 = getOperandMemoryLocation0(operand, isMayAccess)
|
||||||
|
|
|
||||||
|
result = use0
|
||||||
|
or
|
||||||
|
// If `use0` overlaps with a busy definition we turn it into a use
|
||||||
|
// of `UnknownMemoryLocation`.
|
||||||
|
not use0 instanceof MemoryLocation and
|
||||||
|
result = TUnknownMemoryLocation(operand.getEnclosingIRFunction(), isMayAccess)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/** Gets the start bit offset of a `MemoryLocation`, if any. */
|
/** Gets the start bit offset of a `MemoryLocation`, if any. */
|
||||||
int getStartBitOffset(VariableMemoryLocation location) {
|
int getStartBitOffset(VariableMemoryLocation location) {
|
||||||
result = location.getStartBitOffset() and Ints::hasValue(result)
|
result = location.getStartBitOffset() and Ints::hasValue(result)
|
||||||
|
|||||||
@@ -933,11 +933,15 @@ module DefUse {
|
|||||||
bindingset[index, block]
|
bindingset[index, block]
|
||||||
pragma[inline_late]
|
pragma[inline_late]
|
||||||
private int getNonChiOffset(int index, OldBlock block) {
|
private int getNonChiOffset(int index, OldBlock block) {
|
||||||
exists(IRFunction func | func = block.getEnclosingIRFunction() |
|
exists(OldIR::IRFunction func, Instruction i, OldBlock entryBlock |
|
||||||
|
func = block.getEnclosingIRFunction() and
|
||||||
|
i = block.getInstruction(index) and
|
||||||
|
entryBlock = func.getEntryBlock()
|
||||||
|
|
|
||||||
if
|
if
|
||||||
getNewBlock(block) = func.getEntryBlock() and
|
block = entryBlock and
|
||||||
not block.getInstruction(index) instanceof InitializeNonLocalInstruction and
|
not i instanceof InitializeNonLocalInstruction and
|
||||||
not block.getInstruction(index) instanceof AliasedDefinitionInstruction
|
not i instanceof AliasedDefinitionInstruction
|
||||||
then result = 2 * (index + count(VariableGroup vg | vg.getIRFunction() = func))
|
then result = 2 * (index + count(VariableGroup vg | vg.getIRFunction() = func))
|
||||||
else result = 2 * index
|
else result = 2 * index
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -338,6 +338,56 @@ private predicate resultEscapesNonReturn(Instruction instr) {
|
|||||||
not instr.isResultModeled()
|
not instr.isResultModeled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Holds if `operand` may (transitively) flow to an `AddressOperand`. */
|
||||||
|
private predicate consumedAsAddressOperand(Operand operand) {
|
||||||
|
operand instanceof AddressOperand
|
||||||
|
or
|
||||||
|
exists(Operand address |
|
||||||
|
consumedAsAddressOperand(address) and
|
||||||
|
operandIsPropagated(operand, _, address.getDef())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `operand` may originate from a base instruction of an allocation,
|
||||||
|
* and that operand may transitively flow to an `AddressOperand`.
|
||||||
|
*/
|
||||||
|
private predicate propagatedFromAllocationBase(Operand operand, Configuration::Allocation allocation) {
|
||||||
|
consumedAsAddressOperand(operand) and
|
||||||
|
(
|
||||||
|
not exists(Configuration::getOldAllocation(allocation)) and
|
||||||
|
operand.getDef() = allocation.getABaseInstruction()
|
||||||
|
or
|
||||||
|
exists(Operand address |
|
||||||
|
operandIsPropagated(address, _, operand.getDef()) and
|
||||||
|
propagatedFromAllocationBase(address, allocation)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private predicate propagatedFromNonAllocationBase(Operand operand) {
|
||||||
|
exists(Instruction def |
|
||||||
|
def = operand.getDef() and
|
||||||
|
not operandIsPropagated(_, _, def) and
|
||||||
|
not def = any(Configuration::Allocation allocation).getABaseInstruction()
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(Operand address |
|
||||||
|
operandIsPropagated(address, _, operand.getDef()) and
|
||||||
|
propagatedFromNonAllocationBase(address)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if we cannot see all producers of an operand for which allocation also flows into.
|
||||||
|
*/
|
||||||
|
private predicate operandConsumesEscaped(Configuration::Allocation allocation) {
|
||||||
|
exists(AddressOperand address |
|
||||||
|
propagatedFromAllocationBase(address, allocation) and
|
||||||
|
propagatedFromNonAllocationBase(address)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the address of `allocation` escapes outside the domain of the analysis. This can occur
|
* Holds if the address of `allocation` escapes outside the domain of the analysis. This can occur
|
||||||
* either because the allocation's address is taken within the function and escapes, or because the
|
* either because the allocation's address is taken within the function and escapes, or because the
|
||||||
@@ -346,12 +396,14 @@ private predicate resultEscapesNonReturn(Instruction instr) {
|
|||||||
predicate allocationEscapes(Configuration::Allocation allocation) {
|
predicate allocationEscapes(Configuration::Allocation allocation) {
|
||||||
allocation.alwaysEscapes()
|
allocation.alwaysEscapes()
|
||||||
or
|
or
|
||||||
exists(IREscapeAnalysisConfiguration config |
|
exists(IREscapeAnalysisConfiguration config | config.useSoundEscapeAnalysis() |
|
||||||
config.useSoundEscapeAnalysis() and resultEscapesNonReturn(allocation.getABaseInstruction())
|
resultEscapesNonReturn(allocation.getABaseInstruction())
|
||||||
|
or
|
||||||
|
operandConsumesEscaped(allocation)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
Configuration::phaseNeedsSoundEscapeAnalysis() and
|
Configuration::phaseNeedsSoundEscapeAnalysis() and
|
||||||
resultEscapesNonReturn(allocation.getABaseInstruction())
|
(resultEscapesNonReturn(allocation.getABaseInstruction()) or operandConsumesEscaped(allocation))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
private import AliasConfigurationImports
|
private import AliasConfigurationImports
|
||||||
|
private import codeql.util.Unit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A memory allocation that can be tracked by the SimpleSSA alias analysis.
|
* A memory allocation that can be tracked by the SimpleSSA alias analysis.
|
||||||
@@ -16,3 +17,5 @@ class Allocation extends IRAutomaticVariable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
predicate phaseNeedsSoundEscapeAnalysis() { any() }
|
predicate phaseNeedsSoundEscapeAnalysis() { any() }
|
||||||
|
|
||||||
|
Unit getOldAllocation(Allocation allocation) { any() }
|
||||||
|
|||||||
@@ -933,11 +933,15 @@ module DefUse {
|
|||||||
bindingset[index, block]
|
bindingset[index, block]
|
||||||
pragma[inline_late]
|
pragma[inline_late]
|
||||||
private int getNonChiOffset(int index, OldBlock block) {
|
private int getNonChiOffset(int index, OldBlock block) {
|
||||||
exists(IRFunction func | func = block.getEnclosingIRFunction() |
|
exists(OldIR::IRFunction func, Instruction i, OldBlock entryBlock |
|
||||||
|
func = block.getEnclosingIRFunction() and
|
||||||
|
i = block.getInstruction(index) and
|
||||||
|
entryBlock = func.getEntryBlock()
|
||||||
|
|
|
||||||
if
|
if
|
||||||
getNewBlock(block) = func.getEntryBlock() and
|
block = entryBlock and
|
||||||
not block.getInstruction(index) instanceof InitializeNonLocalInstruction and
|
not i instanceof InitializeNonLocalInstruction and
|
||||||
not block.getInstruction(index) instanceof AliasedDefinitionInstruction
|
not i instanceof AliasedDefinitionInstruction
|
||||||
then result = 2 * (index + count(VariableGroup vg | vg.getIRFunction() = func))
|
then result = 2 * (index + count(VariableGroup vg | vg.getIRFunction() = func))
|
||||||
else result = 2 * index
|
else result = 2 * index
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import AliasAnalysis
|
import AliasAnalysis
|
||||||
private import SimpleSSAImports
|
private import SimpleSSAImports
|
||||||
import SimpleSSAPublicImports
|
import SimpleSSAPublicImports
|
||||||
private import AliasConfiguration
|
import AliasConfiguration
|
||||||
private import codeql.util.Unit
|
private import codeql.util.Unit
|
||||||
|
|
||||||
private predicate isTotalAccess(Allocation var, AddressOperand addrOperand, IRType type) {
|
private predicate isTotalAccess(Allocation var, AddressOperand addrOperand, IRType type) {
|
||||||
|
|||||||
@@ -27,6 +27,11 @@ private import implementations.StdPair
|
|||||||
private import implementations.StdMap
|
private import implementations.StdMap
|
||||||
private import implementations.StdSet
|
private import implementations.StdSet
|
||||||
private import implementations.StdString
|
private import implementations.StdString
|
||||||
|
private import implementations.StdFunction
|
||||||
|
private import implementations.StdException
|
||||||
|
private import implementations.StdAllocator
|
||||||
|
private import implementations.StdAlgorithm
|
||||||
|
private import implementations.StdMath
|
||||||
private import implementations.Swap
|
private import implementations.Swap
|
||||||
private import implementations.GetDelim
|
private import implementations.GetDelim
|
||||||
private import implementations.SmartPointer
|
private import implementations.SmartPointer
|
||||||
|
|||||||
@@ -86,6 +86,41 @@ private class StdIterator extends Iterator, Class {
|
|||||||
override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
|
override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class StdReverseIterator extends Iterator, Class {
|
||||||
|
StdReverseIterator() { this.hasQualifiedName(["std", "bsl"], "reverse_iterator") }
|
||||||
|
|
||||||
|
override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdIstreamBufIterator extends Iterator, Class {
|
||||||
|
StdIstreamBufIterator() { this.hasQualifiedName(["std", "bsl"], "istreambuf_iterator") }
|
||||||
|
|
||||||
|
override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdIstreambufIteratorConstructor extends Constructor, SideEffectFunction,
|
||||||
|
AliasFunction
|
||||||
|
{
|
||||||
|
StdIstreambufIteratorConstructor() { this.getDeclaringType() instanceof StdIstreamBufIterator }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `FunctionInput` corresponding to an iterator parameter to
|
* Gets the `FunctionInput` corresponding to an iterator parameter to
|
||||||
* user-defined operator `op`, at `index`.
|
* user-defined operator `op`, at `index`.
|
||||||
@@ -579,23 +614,43 @@ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMe
|
|||||||
override predicate parameterEscapesOnlyViaReturn(int index) { index = -1 }
|
override predicate parameterEscapesOnlyViaReturn(int index) { index = -1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string beginName() {
|
||||||
|
result = ["begin", "cbegin", "rbegin", "crbegin", "before_begin", "cbefore_begin"]
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A `begin` member function, or a related function, that returns an iterator.
|
* A `begin` member function, or a related function, that returns an iterator.
|
||||||
*/
|
*/
|
||||||
class BeginFunction extends MemberFunction {
|
class BeginFunction extends Function {
|
||||||
BeginFunction() {
|
BeginFunction() {
|
||||||
this.hasName(["begin", "cbegin", "rbegin", "crbegin", "before_begin", "cbefore_begin"]) and
|
this.getUnspecifiedType() instanceof Iterator and
|
||||||
this.getType().getUnspecifiedType() instanceof Iterator
|
(
|
||||||
|
this.hasName(beginName()) and
|
||||||
|
this instanceof MemberFunction
|
||||||
|
or
|
||||||
|
this.hasGlobalOrStdOrBslName(beginName()) and
|
||||||
|
not this instanceof MemberFunction and
|
||||||
|
this.getNumberOfParameters() = 1
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string endName() { result = ["end", "cend", "rend", "crend"] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An `end` member function, or a related function, that returns an iterator.
|
* An `end` member function, or a related function, that returns an iterator.
|
||||||
*/
|
*/
|
||||||
class EndFunction extends MemberFunction {
|
class EndFunction extends Function {
|
||||||
EndFunction() {
|
EndFunction() {
|
||||||
this.hasName(["end", "cend", "rend", "crend"]) and
|
this.getUnspecifiedType() instanceof Iterator and
|
||||||
this.getType().getUnspecifiedType() instanceof Iterator
|
(
|
||||||
|
this.hasName(endName()) and
|
||||||
|
this instanceof MemberFunction
|
||||||
|
or
|
||||||
|
this.hasGlobalOrStdOrBslName(endName()) and
|
||||||
|
this instanceof MemberFunction and
|
||||||
|
this.getNumberOfParameters() = 1
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,7 +658,7 @@ class EndFunction extends MemberFunction {
|
|||||||
* A `begin` or `end` member function, or a related member function, that
|
* A `begin` or `end` member function, or a related member function, that
|
||||||
* returns an iterator.
|
* returns an iterator.
|
||||||
*/
|
*/
|
||||||
class BeginOrEndFunction extends MemberFunction {
|
class BeginOrEndFunction extends Function {
|
||||||
BeginOrEndFunction() {
|
BeginOrEndFunction() {
|
||||||
this instanceof BeginFunction or
|
this instanceof BeginFunction or
|
||||||
this instanceof EndFunction
|
this instanceof EndFunction
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
import semmle.code.cpp.models.interfaces.FormattingFunction
|
import semmle.code.cpp.models.interfaces.FormattingFunction
|
||||||
import semmle.code.cpp.models.interfaces.Alias
|
import semmle.code.cpp.models.interfaces.Alias
|
||||||
|
import semmle.code.cpp.models.interfaces.SideEffect
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The standard functions `printf`, `wprintf` and their glib variants.
|
* The standard functions `printf`, `wprintf` and their glib variants.
|
||||||
@@ -96,7 +97,7 @@ private class Sprintf extends FormattingFunction {
|
|||||||
/**
|
/**
|
||||||
* Implements `Snprintf`.
|
* Implements `Snprintf`.
|
||||||
*/
|
*/
|
||||||
private class SnprintfImpl extends Snprintf {
|
private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction {
|
||||||
SnprintfImpl() {
|
SnprintfImpl() {
|
||||||
this instanceof TopLevelFunction and
|
this instanceof TopLevelFunction and
|
||||||
(
|
(
|
||||||
@@ -143,6 +144,26 @@ private class SnprintfImpl extends Snprintf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override int getSizeParameterIndex() { result = 1 }
|
override int getSizeParameterIndex() { result = 1 }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) {
|
||||||
|
// We don't know how many parameters are passed to the function since it's varargs, but they also don't escape.
|
||||||
|
index = this.getFormatParameterIndex()
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = this.getOutputParameterIndex(false) and buffer = true and mustWrite = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
// We don't know how many parameters are passed to the function since it's varargs, but they also have read side effects.
|
||||||
|
i = this.getFormatParameterIndex() and buffer = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* Provides models for C++ functions from the `algorithms` header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import semmle.code.cpp.models.interfaces.Taint
|
||||||
|
import semmle.code.cpp.models.interfaces.DataFlow
|
||||||
|
import semmle.code.cpp.models.interfaces.Iterator
|
||||||
|
import semmle.code.cpp.models.interfaces.SideEffect
|
||||||
|
import semmle.code.cpp.models.interfaces.Alias
|
||||||
|
|
||||||
|
private class StdPartialSort extends Function, SideEffectFunction, AliasFunction {
|
||||||
|
StdPartialSort() { this.hasGlobalOrStdName("partial_sort") }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = this.getAnIteratorParameterIndex() and buffer = true and mustWrite = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = this.getAnIteratorParameterIndex() and
|
||||||
|
buffer = true and
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getAnIteratorParameterIndex() {
|
||||||
|
this.getParameter(result).getUnspecifiedType() instanceof Iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) {
|
||||||
|
index = this.getAnIteratorParameterIndex()
|
||||||
|
or
|
||||||
|
this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdSortHeap extends Function, SideEffectFunction, AliasFunction {
|
||||||
|
StdSortHeap() { this.hasGlobalOrStdName("sort_heap") }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = this.getAnIteratorParameterIndex() and buffer = true and mustWrite = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = this.getAnIteratorParameterIndex() and
|
||||||
|
buffer = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getAnIteratorParameterIndex() {
|
||||||
|
this.getParameter(result).getUnspecifiedType() instanceof Iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = this.getAnIteratorParameterIndex() }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdGenerateN extends Function, SideEffectFunction, AliasFunction {
|
||||||
|
StdGenerateN() { this.hasGlobalOrStdName("generate_n") }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = this.getAnIteratorParameterIndex() and buffer = true and mustWrite = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getAnIteratorParameterIndex() {
|
||||||
|
this.getParameter(result).getUnspecifiedType() instanceof Iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = this.getAnIteratorParameterIndex() }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdFindIfOrIfNot extends Function, SideEffectFunction, AliasFunction {
|
||||||
|
StdFindIfOrIfNot() { this.hasGlobalOrStdName(["find_if", "find_if_not"]) }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = this.getAnIteratorParameterIndex() and buffer = true
|
||||||
|
or
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getAnIteratorParameterIndex() {
|
||||||
|
this.getParameter(result).getUnspecifiedType() instanceof Iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) {
|
||||||
|
this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) {
|
||||||
|
index = this.getAnIteratorParameterIndex()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
/**
|
||||||
|
* Provides models for C++ `allocator` and `allocator_traits` classes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import semmle.code.cpp.models.interfaces.SideEffect
|
||||||
|
import semmle.code.cpp.models.interfaces.Alias
|
||||||
|
|
||||||
|
/** The `std::allocator` class. */
|
||||||
|
class StdAllocator extends Class {
|
||||||
|
StdAllocator() { this.hasGlobalOrStdOrBslName("allocator") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The `std::allocator_traits` class. */
|
||||||
|
class StdAllocatorTraits extends Class {
|
||||||
|
StdAllocatorTraits() { this.hasGlobalOrStdOrBslName("allocator_traits") }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdAllocatorConstructor extends Constructor, AliasFunction, SideEffectFunction {
|
||||||
|
StdAllocatorConstructor() { this.getDeclaringType() instanceof StdAllocator }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false and
|
||||||
|
mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdAllocatorDestructor extends Destructor, AliasFunction, SideEffectFunction {
|
||||||
|
StdAllocatorDestructor() { this.getDeclaringType() instanceof StdAllocator }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false and
|
||||||
|
mustWrite = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdAllocatorAddress extends MemberFunction, AliasFunction, SideEffectFunction {
|
||||||
|
StdAllocatorAddress() { this.getClassAndName("address") instanceof StdAllocator }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdAllocatorAllocate extends MemberFunction, AliasFunction, SideEffectFunction {
|
||||||
|
StdAllocatorAllocate() { this.getClassAndName("allocate") instanceof StdAllocator }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdAllocatorTraitsAllocate extends MemberFunction, AliasFunction, SideEffectFunction {
|
||||||
|
StdAllocatorTraitsAllocate() {
|
||||||
|
this.getClassAndName(["allocate", "allocate_at_least"]) instanceof StdAllocatorTraits
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) {
|
||||||
|
this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdAllocatorDeallocate extends MemberFunction, AliasFunction, SideEffectFunction {
|
||||||
|
StdAllocatorDeallocate() { this.getClassAndName("deallocate") instanceof StdAllocator }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = 0 and
|
||||||
|
buffer = false and
|
||||||
|
mustWrite = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = 0 and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdAllocatorTraitsDeallocate extends MemberFunction, AliasFunction, SideEffectFunction
|
||||||
|
{
|
||||||
|
StdAllocatorTraitsDeallocate() {
|
||||||
|
this.getClassAndName("deallocate") instanceof StdAllocatorTraits
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = [0, 1] }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = 1 and
|
||||||
|
buffer = false and
|
||||||
|
mustWrite = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = [0, 1] and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdAllocatorMaxSize extends MemberFunction, AliasFunction, SideEffectFunction {
|
||||||
|
StdAllocatorMaxSize() { this.getClassAndName("max_size") instanceof StdAllocator }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdAllocatTraitsMaxSize extends MemberFunction, AliasFunction, SideEffectFunction {
|
||||||
|
StdAllocatTraitsMaxSize() { this.getClassAndName("max_size") instanceof StdAllocatorTraits }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdAllocatorConstruct extends MemberFunction, AliasFunction, SideEffectFunction {
|
||||||
|
StdAllocatorConstruct() { this.getClassAndName("construct") instanceof StdAllocator }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = 0 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StdAllocatorTraitsConstruct extends MemberFunction, AliasFunction, SideEffectFunction {
|
||||||
|
StdAllocatorTraitsConstruct() { this.getClassAndName("construct") instanceof StdAllocatorTraits }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) {
|
||||||
|
index = 1 or this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = 1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StdAllocatorDestroy extends MemberFunction, AliasFunction, SideEffectFunction {
|
||||||
|
StdAllocatorDestroy() { this.getClassAndName("destroy") instanceof StdAllocator }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = 0 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = 0 and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StdAllocatorTraitsDestroy extends MemberFunction, AliasFunction, SideEffectFunction {
|
||||||
|
StdAllocatorTraitsDestroy() { this.getClassAndName("destroy") instanceof StdAllocatorTraits }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = [0, 1] }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = 1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = 0 and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
import semmle.code.cpp.models.interfaces.FlowSource
|
import semmle.code.cpp.models.interfaces.FlowSource
|
||||||
import semmle.code.cpp.models.interfaces.Iterator
|
import semmle.code.cpp.models.interfaces.Iterator
|
||||||
|
import semmle.code.cpp.models.interfaces.SideEffect
|
||||||
|
import semmle.code.cpp.models.interfaces.Alias
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A sequence container template class (for example, `std::vector`) from the
|
* A sequence container template class (for example, `std::vector`) from the
|
||||||
@@ -58,7 +60,7 @@ private class Vector extends StdSequenceContainer {
|
|||||||
/**
|
/**
|
||||||
* The standard container functions `push_back` and `push_front`.
|
* The standard container functions `push_back` and `push_front`.
|
||||||
*/
|
*/
|
||||||
class StdSequenceContainerPush extends MemberFunction {
|
class StdSequenceContainerPush extends MemberFunction, SideEffectFunction, AliasFunction {
|
||||||
StdSequenceContainerPush() {
|
StdSequenceContainerPush() {
|
||||||
this.getClassAndName("push_back") instanceof Vector or
|
this.getClassAndName("push_back") instanceof Vector or
|
||||||
this.getClassAndName(["push_back", "push_front"]) instanceof Deque or
|
this.getClassAndName(["push_back", "push_front"]) instanceof Deque or
|
||||||
@@ -74,12 +76,115 @@ class StdSequenceContainerPush extends MemberFunction {
|
|||||||
this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
|
this.getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
|
||||||
this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
|
this.getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false and
|
||||||
|
mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
// the `std::vector<bool>` specialization doesn't take a reference as a
|
||||||
|
// parameter. So we need to check that the parameter is actually a
|
||||||
|
// reference.
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdSequenceContainerPopFrontOrBack extends MemberFunction, SideEffectFunction,
|
||||||
|
AliasFunction
|
||||||
|
{
|
||||||
|
StdSequenceContainerPopFrontOrBack() {
|
||||||
|
this.getClassAndName("pop_back") instanceof Vector or
|
||||||
|
this.getClassAndName("pop_front") instanceof ForwardList or
|
||||||
|
this.getClassAndName(["pop_front", "pop_back"]) instanceof Deque or
|
||||||
|
this.getClassAndName(["pop_front", "pop_back"]) instanceof List
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false and
|
||||||
|
mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdSequenceContainerClear extends MemberFunction, SideEffectFunction, AliasFunction {
|
||||||
|
StdSequenceContainerClear() {
|
||||||
|
this.getClassAndName("clear") instanceof Vector or
|
||||||
|
this.getClassAndName("clear") instanceof Deque or
|
||||||
|
this.getClassAndName("clear") instanceof ForwardList or
|
||||||
|
this.getClassAndName("clear") instanceof List
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false and
|
||||||
|
mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdVectorReserve extends MemberFunction, SideEffectFunction, AliasFunction {
|
||||||
|
StdVectorReserve() { this.getClassAndName("reserve") instanceof Vector }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false and
|
||||||
|
mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The standard container functions `insert` and `insert_after`.
|
* The standard container functions `insert` and `insert_after`.
|
||||||
*/
|
*/
|
||||||
class StdSequenceContainerInsert extends MemberFunction {
|
class StdSequenceContainerInsert extends MemberFunction, SideEffectFunction, AliasFunction {
|
||||||
StdSequenceContainerInsert() {
|
StdSequenceContainerInsert() {
|
||||||
this.getClassAndName("insert") instanceof Deque or
|
this.getClassAndName("insert") instanceof Deque or
|
||||||
this.getClassAndName("insert") instanceof List or
|
this.getClassAndName("insert") instanceof List or
|
||||||
@@ -100,17 +205,138 @@ class StdSequenceContainerInsert extends MemberFunction {
|
|||||||
* Gets the index of a parameter to this function that is an iterator.
|
* Gets the index of a parameter to this function that is an iterator.
|
||||||
*/
|
*/
|
||||||
int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator }
|
int getAnIteratorParameterIndex() { this.getParameter(result).getType() instanceof Iterator }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false and
|
||||||
|
mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdSequenceContainerFrontBack extends MemberFunction, SideEffectFunction,
|
||||||
|
AliasFunction
|
||||||
|
{
|
||||||
|
StdSequenceContainerFrontBack() {
|
||||||
|
this.getClassAndName(["front", "back"]) instanceof Deque or
|
||||||
|
this.getClassAndName(["front", "back"]) instanceof List or
|
||||||
|
this.getClassAndName(["front", "back"]) instanceof Vector or
|
||||||
|
// forward_list does not have a 'back' member function
|
||||||
|
this.getClassAndName("front") instanceof ForwardList
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The standard container functions `at` and `operator[]`.
|
* The standard container functions `at` and `operator[]`.
|
||||||
*/
|
*/
|
||||||
class StdSequenceContainerAt extends MemberFunction {
|
class StdSequenceContainerAt extends MemberFunction, SideEffectFunction, AliasFunction {
|
||||||
StdSequenceContainerAt() {
|
StdSequenceContainerAt() {
|
||||||
this.getClassAndName(["at", "operator[]"]) instanceof Array or
|
this.getClassAndName(["at", "operator[]"]) instanceof Array or
|
||||||
this.getClassAndName(["at", "operator[]"]) instanceof Deque or
|
this.getClassAndName(["at", "operator[]"]) instanceof Deque or
|
||||||
this.getClassAndName(["at", "operator[]"]) instanceof Vector
|
this.getClassAndName(["at", "operator[]"]) instanceof Vector
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdSequenceContainerMemberEquals extends MemberFunction, SideEffectFunction,
|
||||||
|
AliasFunction
|
||||||
|
{
|
||||||
|
StdSequenceContainerMemberEquals() {
|
||||||
|
this.getClassAndName("operator==") instanceof Array or
|
||||||
|
this.getClassAndName("operator==") instanceof Deque or
|
||||||
|
this.getClassAndName("operator==") instanceof Vector
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 or index = 0 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
or
|
||||||
|
i = 0 and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdSequenceContainerEquals extends Function, SideEffectFunction, AliasFunction {
|
||||||
|
StdSequenceContainerEquals() {
|
||||||
|
this.hasGlobalOrStdOrBslName("operator==") and
|
||||||
|
not this instanceof MemberFunction and
|
||||||
|
this.getNumberOfParameters() = 2 and
|
||||||
|
(
|
||||||
|
this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Vector and
|
||||||
|
this.getParameter(1).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Vector
|
||||||
|
or
|
||||||
|
this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof List and
|
||||||
|
this.getParameter(1).getUnspecifiedType().(ReferenceType).getBaseType() instanceof List
|
||||||
|
or
|
||||||
|
this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Deque and
|
||||||
|
this.getParameter(1).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Deque
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = 0 or index = 1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = [0, 1] and buffer = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,6 +368,115 @@ class StdVectorEmplace extends StdSequenceEmplace {
|
|||||||
StdVectorEmplace() { this.getDeclaringType() instanceof Vector }
|
StdVectorEmplace() { this.getDeclaringType() instanceof Vector }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class StdSequenceSize extends MemberFunction, SideEffectFunction, AliasFunction {
|
||||||
|
StdSequenceSize() {
|
||||||
|
this.getClassAndName("size") instanceof Vector
|
||||||
|
or
|
||||||
|
this.getClassAndName("size") instanceof List
|
||||||
|
or
|
||||||
|
this.getClassAndName("size") instanceof Deque
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdSequenceDestructor extends Destructor, SideEffectFunction, AliasFunction {
|
||||||
|
StdSequenceDestructor() {
|
||||||
|
this.getDeclaringType() instanceof Vector
|
||||||
|
or
|
||||||
|
this.getDeclaringType() instanceof List
|
||||||
|
or
|
||||||
|
this.getDeclaringType() instanceof Deque
|
||||||
|
}
|
||||||
|
|
||||||
|
private Destructor getElementDestructor() {
|
||||||
|
result.getDeclaringType() = this.getTemplateArgument(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() {
|
||||||
|
this.getElementDestructor().(SideEffectFunction).hasOnlySpecificReadSideEffects()
|
||||||
|
or
|
||||||
|
not exists(this.getElementDestructor())
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() {
|
||||||
|
this.getElementDestructor().(SideEffectFunction).hasOnlySpecificWriteSideEffects()
|
||||||
|
or
|
||||||
|
not exists(this.getElementDestructor())
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdSequenceConstructor extends Constructor, SideEffectFunction, AliasFunction {
|
||||||
|
StdSequenceConstructor() {
|
||||||
|
this.getDeclaringType() instanceof Vector
|
||||||
|
or
|
||||||
|
this.getDeclaringType() instanceof List
|
||||||
|
or
|
||||||
|
this.getDeclaringType() instanceof Deque
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InitializerList extends Class {
|
||||||
|
InitializerList() { this.hasQualifiedName(["std", "bsl"], "initializer_list") }
|
||||||
|
|
||||||
|
Type getElementType() { result = this.getTemplateArgument(0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class InitializerListConstructor extends Constructor, SideEffectFunction, AliasFunction {
|
||||||
|
InitializerListConstructor() { this.getDeclaringType() instanceof InitializerList }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The standard vector `emplace_back` function.
|
* The standard vector `emplace_back` function.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* Provides models for the C++ `std::exception` class and subclasses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import semmle.code.cpp.models.interfaces.Taint
|
||||||
|
import semmle.code.cpp.models.interfaces.Alias
|
||||||
|
import semmle.code.cpp.models.interfaces.SideEffect
|
||||||
|
|
||||||
|
/** The `std::exception` class. */
|
||||||
|
class StdException extends Class {
|
||||||
|
StdException() { this.hasGlobalOrStdOrBslName("exception") }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The `std::bad_alloc` class. */
|
||||||
|
class StdBadAllocException extends Class {
|
||||||
|
StdBadAllocException() { this.hasGlobalOrStdOrBslName("bad_alloc") }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdBadAllocExceptionConstructor extends Constructor, SideEffectFunction, AliasFunction
|
||||||
|
{
|
||||||
|
StdBadAllocExceptionConstructor() { this.getDeclaringType() instanceof StdBadAllocException }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* Provides models for C++ `std::function` class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import semmle.code.cpp.models.interfaces.SideEffect
|
||||||
|
import semmle.code.cpp.models.interfaces.Alias
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An instantiation of the `std::function` class template.
|
||||||
|
*/
|
||||||
|
class StdFunction extends ClassTemplateInstantiation {
|
||||||
|
StdFunction() { this.hasGlobalOrStdOrBslName("function") }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdFunctionConstructor extends Constructor, SideEffectFunction, AliasFunction {
|
||||||
|
StdFunctionConstructor() { this.getDeclaringType() instanceof StdFunction }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdFunctionDestructor extends Destructor, SideEffectFunction, AliasFunction {
|
||||||
|
StdFunctionDestructor() { this.getDeclaringType() instanceof StdFunction }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@
|
|||||||
import semmle.code.cpp.models.interfaces.Taint
|
import semmle.code.cpp.models.interfaces.Taint
|
||||||
import semmle.code.cpp.models.interfaces.DataFlow
|
import semmle.code.cpp.models.interfaces.DataFlow
|
||||||
import semmle.code.cpp.models.interfaces.Iterator
|
import semmle.code.cpp.models.interfaces.Iterator
|
||||||
|
import semmle.code.cpp.models.interfaces.SideEffect
|
||||||
|
import semmle.code.cpp.models.interfaces.Alias
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `std::map` and `std::unordered_map` template classes.
|
* The `std::map` and `std::unordered_map` template classes.
|
||||||
@@ -16,7 +18,9 @@ private class MapOrUnorderedMap extends Class {
|
|||||||
/**
|
/**
|
||||||
* Additional model for map constructors using iterator inputs.
|
* Additional model for map constructors using iterator inputs.
|
||||||
*/
|
*/
|
||||||
private class StdMapConstructor extends Constructor, TaintFunction {
|
private class StdMapConstructor extends Constructor, TaintFunction, AliasFunction,
|
||||||
|
SideEffectFunction
|
||||||
|
{
|
||||||
StdMapConstructor() { this.getDeclaringType() instanceof MapOrUnorderedMap }
|
StdMapConstructor() { this.getDeclaringType() instanceof MapOrUnorderedMap }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,6 +39,23 @@ private class StdMapConstructor extends Constructor, TaintFunction {
|
|||||||
output.isQualifierObject()
|
output.isQualifierObject()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,7 +154,7 @@ class StdMapAt extends MemberFunction {
|
|||||||
StdMapAt() { this.getClassAndName(["at", "operator[]"]) instanceof MapOrUnorderedMap }
|
StdMapAt() { this.getClassAndName(["at", "operator[]"]) instanceof MapOrUnorderedMap }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class StdMapAtModels extends StdMapAt, TaintFunction {
|
private class StdMapAtModels extends StdMapAt, TaintFunction, AliasFunction, SideEffectFunction {
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
// flow from qualifier to referenced return value
|
// flow from qualifier to referenced return value
|
||||||
input.isQualifierObject() and
|
input.isQualifierObject() and
|
||||||
@@ -144,6 +165,18 @@ private class StdMapAtModels extends StdMapAt, TaintFunction {
|
|||||||
output.isQualifierObject()
|
output.isQualifierObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
}
|
||||||
|
|
||||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,3 +220,63 @@ private class StdMapEqualRange extends TaintFunction {
|
|||||||
output.isReturnValue()
|
output.isReturnValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class StdMapDestructor extends Destructor, SideEffectFunction, AliasFunction {
|
||||||
|
StdMapDestructor() { this.getDeclaringType() instanceof MapOrUnorderedMap }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdMapClear extends MemberFunction, SideEffectFunction, AliasFunction {
|
||||||
|
StdMapClear() { this.getClassAndName("clear") instanceof MapOrUnorderedMap }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false and
|
||||||
|
mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StdMapSize extends MemberFunction, SideEffectFunction, AliasFunction {
|
||||||
|
StdMapSize() { this.getClassAndName("size") instanceof MapOrUnorderedMap }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
108
cpp/ql/lib/semmle/code/cpp/models/implementations/StdMath.qll
Normal file
108
cpp/ql/lib/semmle/code/cpp/models/implementations/StdMath.qll
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* Provides models for C++ functions from the `cmath` header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private import semmle.code.cpp.models.interfaces.SideEffect
|
||||||
|
private import semmle.code.cpp.models.interfaces.Alias
|
||||||
|
|
||||||
|
private class LdExp extends Function, SideEffectFunction {
|
||||||
|
LdExp() { this.hasGlobalOrStdOrBslName(["ldexp", "ldexpf", "ldexpl"]) }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Abs extends Function, SideEffectFunction {
|
||||||
|
Abs() { this.hasGlobalOrStdOrBslName(["abs", "fabs", "fabsf", "fabsl", "llabs", "imaxabs"]) }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Div extends Function, SideEffectFunction {
|
||||||
|
Div() { this.hasGlobalOrStdOrBslName(["div", "ldiv", "lldiv", "imaxdiv"]) }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FMod extends Function, SideEffectFunction {
|
||||||
|
FMod() { this.hasGlobalOrStdOrBslName(["fmod", "fmodf", "fmodl"]) }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Remainder extends Function, SideEffectFunction {
|
||||||
|
Remainder() { this.hasGlobalOrStdOrBslName(["remainder", "remainderf", "remainderl"]) }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Remquo extends Function, SideEffectFunction {
|
||||||
|
Remquo() { this.hasGlobalOrStdOrBslName(["remquo", "remquof", "remquol"]) }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof PointerType and
|
||||||
|
buffer = false and
|
||||||
|
mustWrite = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Fma extends Function, SideEffectFunction {
|
||||||
|
Fma() { this.hasGlobalOrStdOrBslName(["fma", "fmaf", "fmal"]) }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Fmax extends Function, SideEffectFunction {
|
||||||
|
Fmax() { this.hasGlobalOrStdOrBslName(["fmax", "fmaxf", "fmaxl"]) }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Fmin extends Function, SideEffectFunction {
|
||||||
|
Fmin() { this.hasGlobalOrStdOrBslName(["fmin", "fminf", "fminl"]) }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Fdim extends Function, SideEffectFunction {
|
||||||
|
Fdim() { this.hasGlobalOrStdOrBslName(["fdim", "fdimf", "fdiml"]) }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Nan extends Function, SideEffectFunction, AliasFunction {
|
||||||
|
Nan() { this.hasGlobalOrStdOrBslName(["nan", "nanf", "nanl"]) }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = 0 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = 0 and buffer = true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import semmle.code.cpp.models.interfaces.Taint
|
import semmle.code.cpp.models.interfaces.Taint
|
||||||
|
import semmle.code.cpp.models.interfaces.Alias
|
||||||
|
import semmle.code.cpp.models.interfaces.SideEffect
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instantiation of `std::pair<T1, T2>`.
|
* An instantiation of `std::pair<T1, T2>`.
|
||||||
@@ -37,7 +39,9 @@ class StdPairCopyishConstructor extends Constructor, TaintFunction {
|
|||||||
/**
|
/**
|
||||||
* Additional model for `std::pair` constructors.
|
* Additional model for `std::pair` constructors.
|
||||||
*/
|
*/
|
||||||
private class StdPairConstructor extends Constructor, TaintFunction {
|
private class StdPairConstructor extends Constructor, TaintFunction, AliasFunction,
|
||||||
|
SideEffectFunction
|
||||||
|
{
|
||||||
StdPairConstructor() { this.getDeclaringType() instanceof StdPair }
|
StdPairConstructor() { this.getDeclaringType() instanceof StdPair }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,4 +63,77 @@ private class StdPairConstructor extends Constructor, TaintFunction {
|
|||||||
output.isQualifierObject()
|
output.isQualifierObject()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
// All the constructor parameters are references with the exception of this one:
|
||||||
|
// ```
|
||||||
|
// template<class... Args1, class... Args2>
|
||||||
|
// pair(std::piecewise_construct_t, std::tuple<Args1...> first_args, std::tuple<Args2...> second_args);
|
||||||
|
// ```
|
||||||
|
// So we need to check that the parameters are actually references
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
|
||||||
|
buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdPairDestructor extends Destructor, AliasFunction, SideEffectFunction {
|
||||||
|
StdPairDestructor() { this.getDeclaringType() instanceof StdPair }
|
||||||
|
|
||||||
|
private Type getFirstType() { result = this.getDeclaringType().getTemplateArgument(0) }
|
||||||
|
|
||||||
|
private Type getSecondType() { result = this.getDeclaringType().getTemplateArgument(0) }
|
||||||
|
|
||||||
|
private Type getAType() { result = [this.getFirstType(), this.getSecondType()] }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the destructor associated with the base type of this pair
|
||||||
|
*/
|
||||||
|
private Destructor getADestructor() { result.getDeclaringType() = this.getAType() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() {
|
||||||
|
this.getADestructor().(SideEffectFunction).hasOnlySpecificReadSideEffects()
|
||||||
|
or
|
||||||
|
// If there's no declared destructor for the base type then it won't have
|
||||||
|
// any strange read side effects.
|
||||||
|
not exists(this.getADestructor())
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() {
|
||||||
|
this.getADestructor().(SideEffectFunction).hasOnlySpecificWriteSideEffects()
|
||||||
|
or
|
||||||
|
// If there's no declared destructor for the base type then it won't have
|
||||||
|
// any strange write side effects.
|
||||||
|
not exists(this.getADestructor())
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) {
|
||||||
|
this.getADestructor().(AliasFunction).parameterNeverEscapes(index)
|
||||||
|
or
|
||||||
|
// If there's no declared destructor for the base type then it won't cause
|
||||||
|
// anything to escape.
|
||||||
|
not exists(this.getADestructor()) and
|
||||||
|
index = -1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
import semmle.code.cpp.models.interfaces.Taint
|
import semmle.code.cpp.models.interfaces.Taint
|
||||||
import semmle.code.cpp.models.interfaces.Iterator
|
import semmle.code.cpp.models.interfaces.Iterator
|
||||||
import semmle.code.cpp.models.interfaces.DataFlow
|
import semmle.code.cpp.models.interfaces.DataFlow
|
||||||
|
import semmle.code.cpp.models.interfaces.SideEffect
|
||||||
|
import semmle.code.cpp.models.interfaces.Alias
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `std::basic_string` template class instantiations.
|
* The `std::basic_string` template class instantiations.
|
||||||
@@ -78,7 +80,9 @@ abstract private class StdStringTaintFunction extends TaintFunction {
|
|||||||
* std::string b(a.begin(), a.end());
|
* std::string b(a.begin(), a.end());
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
private class StdStringConstructor extends Constructor, StdStringTaintFunction {
|
private class StdStringConstructor extends Constructor, StdStringTaintFunction, SideEffectFunction,
|
||||||
|
AliasFunction
|
||||||
|
{
|
||||||
StdStringConstructor() { this.getDeclaringType() instanceof StdBasicString }
|
StdStringConstructor() { this.getDeclaringType() instanceof StdBasicString }
|
||||||
|
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
@@ -94,6 +98,42 @@ private class StdStringConstructor extends Constructor, StdStringTaintFunction {
|
|||||||
output.isQualifierObject()
|
output.isQualifierObject()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class StdStringDestructor extends Destructor, SideEffectFunction, AliasFunction {
|
||||||
|
StdStringDestructor() { this.getDeclaringType() instanceof StdBasicString }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -164,7 +204,7 @@ private class StdStringFrontBack extends StdStringTaintFunction {
|
|||||||
/**
|
/**
|
||||||
* The (non-member) `std::string` function `operator+`.
|
* The (non-member) `std::string` function `operator+`.
|
||||||
*/
|
*/
|
||||||
private class StdStringPlus extends StdStringTaintFunction {
|
private class StdStringPlus extends StdStringTaintFunction, SideEffectFunction, AliasFunction {
|
||||||
StdStringPlus() {
|
StdStringPlus() {
|
||||||
this.hasQualifiedName(["std", "bsl"], "operator+") and
|
this.hasQualifiedName(["std", "bsl"], "operator+") and
|
||||||
this.getUnspecifiedType() instanceof StdBasicString
|
this.getUnspecifiedType() instanceof StdBasicString
|
||||||
@@ -178,6 +218,22 @@ private class StdStringPlus extends StdStringTaintFunction {
|
|||||||
) and
|
) and
|
||||||
output.isReturnValue()
|
output.isReturnValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
|
||||||
|
buffer = false
|
||||||
|
or
|
||||||
|
this.getParameter(i).getUnspecifiedType() instanceof PointerType and
|
||||||
|
buffer = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = [0, 1] }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -185,7 +241,7 @@ private class StdStringPlus extends StdStringTaintFunction {
|
|||||||
* All of these functions combine the existing string with a new
|
* All of these functions combine the existing string with a new
|
||||||
* string (or character) from one of the arguments.
|
* string (or character) from one of the arguments.
|
||||||
*/
|
*/
|
||||||
private class StdStringAppend extends StdStringTaintFunction {
|
private class StdStringAppend extends StdStringTaintFunction, SideEffectFunction, AliasFunction {
|
||||||
StdStringAppend() {
|
StdStringAppend() {
|
||||||
this.getClassAndName(["operator+=", "append", "replace"]) instanceof StdBasicString
|
this.getClassAndName(["operator+=", "append", "replace"]) instanceof StdBasicString
|
||||||
}
|
}
|
||||||
@@ -210,6 +266,22 @@ private class StdStringAppend extends StdStringTaintFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and mustWrite = false and buffer = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = [-1, 0] and buffer = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = [-1, 0] }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -301,7 +373,7 @@ private class StdStringSubstr extends StdStringTaintFunction {
|
|||||||
/**
|
/**
|
||||||
* The `std::string` functions `at` and `operator[]`.
|
* The `std::string` functions `at` and `operator[]`.
|
||||||
*/
|
*/
|
||||||
private class StdStringAt extends StdStringTaintFunction {
|
private class StdStringAt extends StdStringTaintFunction, SideEffectFunction, AliasFunction {
|
||||||
StdStringAt() { this.getClassAndName(["at", "operator[]"]) instanceof StdBasicString }
|
StdStringAt() { this.getClassAndName(["at", "operator[]"]) instanceof StdBasicString }
|
||||||
|
|
||||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||||
@@ -315,6 +387,22 @@ private class StdStringAt extends StdStringTaintFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
override predicate isPartialWrite(FunctionOutput output) { output.isQualifierObject() }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -324,6 +412,54 @@ private class StdBasicIStream extends ClassTemplateInstantiation {
|
|||||||
StdBasicIStream() { this.hasQualifiedName(["std", "bsl"], "basic_istream") }
|
StdBasicIStream() { this.hasQualifiedName(["std", "bsl"], "basic_istream") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class StdBasicIfStream extends ClassTemplateInstantiation {
|
||||||
|
StdBasicIfStream() { this.hasQualifiedName(["std", "bsl"], "basic_ifstream") }
|
||||||
|
}
|
||||||
|
|
||||||
|
class StdBasicIfStreamConstructor extends Constructor, SideEffectFunction, AliasFunction {
|
||||||
|
StdBasicIfStreamConstructor() { this.getDeclaringType() instanceof StdBasicIfStream }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
exists(Type t | t = this.getParameter(i).getUnspecifiedType() |
|
||||||
|
t instanceof PointerType and buffer = true
|
||||||
|
or
|
||||||
|
t instanceof ReferenceType and buffer = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StdBasicIfStreamDestructor extends Destructor, SideEffectFunction, AliasFunction {
|
||||||
|
StdBasicIfStreamDestructor() { this.getDeclaringType() instanceof StdBasicIfStream }
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = -1 }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
i = -1 and buffer = false and mustWrite = true
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = -1 and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `std::istream` function `operator>>` (defined as a member function).
|
* The `std::istream` function `operator>>` (defined as a member function).
|
||||||
*/
|
*/
|
||||||
@@ -542,6 +678,33 @@ private class StdBasicOStream extends ClassTemplateInstantiation {
|
|||||||
StdBasicOStream() { this.hasQualifiedName(["std", "bsl"], "basic_ostream") }
|
StdBasicOStream() { this.hasQualifiedName(["std", "bsl"], "basic_ostream") }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class StdStringLessThan extends Function, AliasFunction, SideEffectFunction {
|
||||||
|
StdStringLessThan() {
|
||||||
|
this.hasQualifiedName(["std", "bsl"], "operator<") and
|
||||||
|
this.getNumberOfParameters() = 2 and
|
||||||
|
this.getParameter(0).getUnspecifiedType().(ReferenceType).getBaseType() instanceof
|
||||||
|
StdBasicString and
|
||||||
|
this.getParameter(1).getUnspecifiedType().(ReferenceType).getBaseType() instanceof
|
||||||
|
StdBasicString
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate parameterNeverEscapes(int index) { index = [0, 1] }
|
||||||
|
|
||||||
|
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||||
|
|
||||||
|
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||||
|
i = [0, 1] and buffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `std::ostream` functions `operator<<` (defined as a member function),
|
* The `std::ostream` functions `operator<<` (defined as a member function),
|
||||||
* `put` and `write`.
|
* `put` and `write`.
|
||||||
|
|||||||
@@ -485,10 +485,17 @@ namespace_decls(
|
|||||||
int bodylocation: @location_default ref
|
int bodylocation: @location_default ref
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case @using.kind of
|
||||||
|
1 = @using_declaration
|
||||||
|
| 2 = @using_directive
|
||||||
|
| 3 = @using_enum_declaration
|
||||||
|
;
|
||||||
|
|
||||||
usings(
|
usings(
|
||||||
unique int id: @using,
|
unique int id: @using,
|
||||||
int element_id: @element ref,
|
int element_id: @element ref,
|
||||||
int location: @location_default ref
|
int location: @location_default ref,
|
||||||
|
int kind: int ref
|
||||||
);
|
);
|
||||||
|
|
||||||
/** The element which contains the `using` declaration. */
|
/** The element which contains the `using` declaration. */
|
||||||
@@ -1358,6 +1365,8 @@ funbind(
|
|||||||
@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr
|
@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Binary encoding of the allocator form.
|
||||||
|
|
||||||
case @allocator.form of
|
case @allocator.form of
|
||||||
0 = plain
|
0 = plain
|
||||||
| 1 = alignment
|
| 1 = alignment
|
||||||
@@ -1376,11 +1385,13 @@ expr_allocator(
|
|||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Binary encoding of the deallocator form.
|
||||||
|
|
||||||
case @deallocator.form of
|
case @deallocator.form of
|
||||||
0 = plain
|
0 = plain
|
||||||
| 1 = size
|
| 1 = size
|
||||||
| 2 = alignment
|
| 2 = alignment
|
||||||
| 3 = size_and_alignment
|
| 4 = destroying_delete
|
||||||
;
|
;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
|||||||
|
description: Support destroying deletes
|
||||||
|
compatibility: partial
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
|||||||
|
description: Support using-enum declarations.
|
||||||
|
compatibility: partial
|
||||||
|
usings.rel: run usings.qlo
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class UsingEntry extends @using {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Element extends @element {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Location extends @location_default {
|
||||||
|
string toString() { none() }
|
||||||
|
}
|
||||||
|
|
||||||
|
from UsingEntry u, Element target, Location loc, int kind
|
||||||
|
where
|
||||||
|
usings(u, target, loc) and
|
||||||
|
if target instanceof @namespace then kind = 2 else kind = 1
|
||||||
|
select u, target, loc, kind
|
||||||
@@ -39,7 +39,7 @@ predicate allocCallOrIndirect(Expr e) {
|
|||||||
allocCallOrIndirect(rtn.getExpr())
|
allocCallOrIndirect(rtn.getExpr())
|
||||||
or
|
or
|
||||||
// return variable assigned with alloc
|
// return variable assigned with alloc
|
||||||
exists(Variable v |
|
exists(StackVariable v |
|
||||||
v = rtn.getExpr().(VariableAccess).getTarget() and
|
v = rtn.getExpr().(VariableAccess).getTarget() and
|
||||||
allocCallOrIndirect(v.getAnAssignedValue()) and
|
allocCallOrIndirect(v.getAnAssignedValue()) and
|
||||||
not assignedToFieldOrGlobal(v, _)
|
not assignedToFieldOrGlobal(v, _)
|
||||||
|
|||||||
@@ -38,11 +38,18 @@ private string getEofValue() {
|
|||||||
private predicate checkedForEof(ScanfFunctionCall call) {
|
private predicate checkedForEof(ScanfFunctionCall call) {
|
||||||
exists(IRGuardCondition gc |
|
exists(IRGuardCondition gc |
|
||||||
exists(Instruction i | i.getUnconvertedResultExpression() = call |
|
exists(Instruction i | i.getUnconvertedResultExpression() = call |
|
||||||
// call == EOF
|
exists(int val | gc.comparesEq(valueNumber(i).getAUse(), val, _, _) |
|
||||||
gc.comparesEq(valueNumber(i).getAUse(), getEofValue().toInt(), _, _)
|
// call == EOF
|
||||||
|
val = getEofValue().toInt()
|
||||||
|
or
|
||||||
|
// call == [any positive number]
|
||||||
|
val > 0
|
||||||
|
)
|
||||||
or
|
or
|
||||||
// call < 0 (EOF is guaranteed to be negative)
|
exists(int val | gc.comparesLt(valueNumber(i).getAUse(), val, true, _) |
|
||||||
gc.comparesLt(valueNumber(i).getAUse(), 0, true, _)
|
// call < [any non-negative number] (EOF is guaranteed to be negative)
|
||||||
|
val >= 0
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import cpp
|
import cpp
|
||||||
import semmle.code.cpp.models.Models
|
import semmle.code.cpp.models.Models
|
||||||
|
import semmle.code.cpp.commons.Buffer
|
||||||
|
|
||||||
predicate baseType(AllocationExpr alloc, Type base) {
|
predicate baseType(AllocationExpr alloc, Type base) {
|
||||||
exists(PointerType pointer |
|
exists(PointerType pointer |
|
||||||
@@ -30,7 +31,8 @@ predicate baseType(AllocationExpr alloc, Type base) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
predicate decideOnSize(Type t, int size) {
|
predicate decideOnSize(Type t, int size) {
|
||||||
// If the codebase has more than one type with the same name, it can have more than one size.
|
// If the codebase has more than one type with the same name, it can have more than one size. For
|
||||||
|
// most purposes in this query, we use the smallest.
|
||||||
size = min(t.getSize())
|
size = min(t.getSize())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +47,8 @@ where
|
|||||||
size = 0 or
|
size = 0 or
|
||||||
(allocated / size) * size = allocated
|
(allocated / size) * size = allocated
|
||||||
) and
|
) and
|
||||||
not basesize > allocated // covered by SizeCheck.ql
|
not basesize > allocated and // covered by SizeCheck.ql
|
||||||
|
not memberMayBeVarSize(base.getUnspecifiedType(), _) // exclude variable size types
|
||||||
select alloc,
|
select alloc,
|
||||||
"Allocated memory (" + allocated.toString() + " bytes) is not a multiple of the size of '" +
|
"Allocated memory (" + allocated.toString() + " bytes) is not a multiple of the size of '" +
|
||||||
base.getName() + "' (" + basesize.toString() + " bytes)."
|
base.getName() + "' (" + basesize.toString() + " bytes)."
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ contains sensitive data that could somehow be retrieved by an attacker.</p>
|
|||||||
</overview>
|
</overview>
|
||||||
<recommendation>
|
<recommendation>
|
||||||
|
|
||||||
<p>Use alternative platform-supplied functions that will not get optimized away. Examples of such
|
<p>Use <code>memset_s</code> (from C11) instead of <code>memset</code>, as <code>memset_s</code> will not
|
||||||
functions include <code>memset_s</code>, <code>SecureZeroMemory</code>, and <code>bzero_explicit</code>.
|
get optimized away. Alternatively use platform-supplied functions such as <code>SecureZeroMemory</code> or
|
||||||
Alternatively, passing the <code>-fno-builtin-memset</code> option to the GCC/Clang compiler usually
|
<code>bzero_explicit</code> that make the same guarantee. Passing the <code>-fno-builtin-memset</code>
|
||||||
also prevents the optimization. Finally, you can use the public-domain <code>secure_memzero</code> function
|
option to the GCC/Clang compiler usually also prevents the optimization. Finally, you can use the
|
||||||
(see references below). This function, however, is not guaranteed to work on all platforms and compilers.</p>
|
public-domain <code>secure_memzero</code> function (see references below). This function, however, is not
|
||||||
|
guaranteed to work on all platforms and compilers.</p>
|
||||||
|
|
||||||
</recommendation>
|
</recommendation>
|
||||||
<example>
|
<example>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* @id cpp/unsigned-difference-expression-compared-zero
|
* @id cpp/unsigned-difference-expression-compared-zero
|
||||||
* @problem.severity warning
|
* @problem.severity warning
|
||||||
* @security-severity 9.8
|
* @security-severity 9.8
|
||||||
* @precision medium
|
* @precision high
|
||||||
* @tags security
|
* @tags security
|
||||||
* correctness
|
* correctness
|
||||||
* external/cwe/cwe-191
|
* external/cwe/cwe-191
|
||||||
|
|||||||
@@ -1,12 +1,31 @@
|
|||||||
void writeCredentials() {
|
#include <sodium.h>
|
||||||
char *password = "cleartext password";
|
#include <stdio.h>
|
||||||
FILE* file = fopen("credentials.txt", "w");
|
#include <string.h>
|
||||||
|
|
||||||
|
void writeCredentialsBad(FILE *file, const char *cleartextCredentials) {
|
||||||
// BAD: write password to disk in cleartext
|
// BAD: write password to disk in cleartext
|
||||||
fputs(password, file);
|
fputs(cleartextCredentials, file);
|
||||||
|
|
||||||
// GOOD: encrypt password first
|
|
||||||
char *encrypted = encrypt(password);
|
|
||||||
fputs(encrypted, file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int writeCredentialsGood(FILE *file, const char *cleartextCredentials, const unsigned char *key, const unsigned char *nonce) {
|
||||||
|
size_t credentialsLen = strlen(cleartextCredentials);
|
||||||
|
size_t ciphertext_len = crypto_secretbox_MACBYTES + credentialsLen;
|
||||||
|
unsigned char *ciphertext = malloc(ciphertext_len);
|
||||||
|
if (!ciphertext) {
|
||||||
|
logError();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// encrypt the password first
|
||||||
|
if (crypto_secretbox_easy(ciphertext, (const unsigned char *)cleartextCredentials, credentialsLen, nonce, key) != 0) {
|
||||||
|
free(ciphertext);
|
||||||
|
logError();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GOOD: write encrypted password to disk
|
||||||
|
fwrite(ciphertext, 1, ciphertext_len, file);
|
||||||
|
|
||||||
|
free(ciphertext);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,11 @@ storing them.</p>
|
|||||||
|
|
||||||
<sample src="CleartextStorage.c" />
|
<sample src="CleartextStorage.c" />
|
||||||
|
|
||||||
|
<p>Note that for the 'GOOD' example to work we need to link against an encryption library (in this case libsodium),
|
||||||
|
initialize it with a call to <code>sodium_init</code>, and create the key and nonce with
|
||||||
|
<code>crypto_secretbox_keygen</code> and <code>randombytes_buf</code> respectively. We also need to store those
|
||||||
|
details securely so they can be used for decryption.</p>
|
||||||
|
|
||||||
</example>
|
</example>
|
||||||
<references>
|
<references>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
void bad(void) {
|
void bad(void) {
|
||||||
char *password = "cleartext password";
|
const char *password = "cleartext password";
|
||||||
sqlite3 *credentialsDB;
|
sqlite3 *credentialsDB;
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
|
|
||||||
@@ -16,14 +16,15 @@ void bad(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void good(void) {
|
void good(const char *secretKey) {
|
||||||
char *password = "cleartext password";
|
const char *password = "cleartext password";
|
||||||
sqlite3 *credentialsDB;
|
sqlite3 *credentialsDB;
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
|
|
||||||
if (sqlite3_open("credentials.db", &credentialsDB) == SQLITE_OK) {
|
if (sqlite3_open("credentials.db", &credentialsDB) == SQLITE_OK) {
|
||||||
// GOOD: database encryption enabled:
|
// GOOD: database encryption enabled:
|
||||||
sqlite3_exec(credentialsDB, "PRAGMA key = 'secretKey!'", NULL, NULL, NULL);
|
std::string setKeyString = std::string("PRAGMA key = '") + secretKey + "'";
|
||||||
|
sqlite3_exec(credentialsDB, setKeyString.c_str(), NULL, NULL, NULL);
|
||||||
sqlite3_exec(credentialsDB, "CREATE TABLE IF NOT EXISTS creds (password TEXT);", NULL, NULL, NULL);
|
sqlite3_exec(credentialsDB, "CREATE TABLE IF NOT EXISTS creds (password TEXT);", NULL, NULL, NULL);
|
||||||
if (sqlite3_prepare_v2(credentialsDB, "INSERT INTO creds(password) VALUES(?)", -1, &stmt, NULL) == SQLITE_OK) {
|
if (sqlite3_prepare_v2(credentialsDB, "INSERT INTO creds(password) VALUES(?)", -1, &stmt, NULL) == SQLITE_OK) {
|
||||||
sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT);
|
sqlite3_bind_text(stmt, 1, password, -1, SQLITE_TRANSIENT);
|
||||||
@@ -33,4 +34,3 @@ void good(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ In the 'GOOD' case, the database (and thus the credentials) are encrypted.</p>
|
|||||||
|
|
||||||
<sample src="CleartextSqliteDatabase.c" />
|
<sample src="CleartextSqliteDatabase.c" />
|
||||||
|
|
||||||
|
<p>Note that for the 'GOOD' example to work we need to provide a secret key. Secure key generation and storage is required.</p>
|
||||||
|
|
||||||
</example>
|
</example>
|
||||||
<references>
|
<references>
|
||||||
|
|
||||||
|
|||||||
@@ -232,6 +232,7 @@ predicate nullCheckInThrowingNew(NewOrNewArrayExpr newExpr, GuardCondition guard
|
|||||||
from NewOrNewArrayExpr newExpr, Element element, string msg, string elementString
|
from NewOrNewArrayExpr newExpr, Element element, string msg, string elementString
|
||||||
where
|
where
|
||||||
not newExpr.isFromUninstantiatedTemplate(_) and
|
not newExpr.isFromUninstantiatedTemplate(_) and
|
||||||
|
not newExpr.isFromTemplateInstantiation(_) and
|
||||||
(
|
(
|
||||||
noThrowInTryBlock(newExpr, element) and
|
noThrowInTryBlock(newExpr, element) and
|
||||||
msg = "This allocation cannot throw. $@ is unnecessary." and
|
msg = "This allocation cannot throw. $@ is unnecessary." and
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: queryMetadata
|
||||||
|
---
|
||||||
|
* The precision of `cpp/unsigned-difference-expression-compared-zero` ("Unsigned difference expression compared to zero") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* The `cpp/incorrect-allocation-error-handling` ("Incorrect allocation-error handling") query no longer produces occasional false positive results inside template instantiations.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* The `cpp/suspicious-allocation-size` ("Not enough memory allocated for array of pointer type") query no longer produces false positives on "variable size" `struct`s.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* The `cpp/incorrectly-checked-scanf` ("Incorrect return-value check for a 'scanf'-like function") query now produces fewer false positive results.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* Fixed false positives in the `cpp/memory-may-not-be-freed` ("Memory may not be freed") query involving class methods that returned an allocated field of that class being misidentified as allocators.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/cpp-queries
|
name: codeql/cpp-queries
|
||||||
version: 1.1.0
|
version: 1.1.1-dev
|
||||||
groups:
|
groups:
|
||||||
- cpp
|
- cpp
|
||||||
- queries
|
- queries
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
// semmle-extractor-options: -std=c++17
|
// semmle-extractor-options: -std=c++20
|
||||||
typedef unsigned long size_t;
|
typedef unsigned long size_t;
|
||||||
namespace std {
|
namespace std {
|
||||||
enum class align_val_t : size_t {};
|
enum class align_val_t : size_t {};
|
||||||
|
|
||||||
|
struct destroying_delete_t {
|
||||||
|
explicit destroying_delete_t() = default;
|
||||||
|
};
|
||||||
|
inline constexpr destroying_delete_t destroying_delete{};
|
||||||
}
|
}
|
||||||
|
|
||||||
void* operator new(size_t, float);
|
void* operator new(size_t, float);
|
||||||
@@ -37,6 +42,11 @@ struct SizedDealloc {
|
|||||||
void operator delete[](void*, size_t);
|
void operator delete[](void*, size_t);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DestroyingDealloc {
|
||||||
|
void* operator new(size_t);
|
||||||
|
void operator delete(DestroyingDealloc*, std::destroying_delete_t);
|
||||||
|
};
|
||||||
|
|
||||||
struct alignas(128) Overaligned {
|
struct alignas(128) Overaligned {
|
||||||
char a[256];
|
char a[256];
|
||||||
};
|
};
|
||||||
@@ -59,6 +69,7 @@ void OperatorDelete() {
|
|||||||
delete static_cast<int*>(nullptr); // No destructor
|
delete static_cast<int*>(nullptr); // No destructor
|
||||||
delete static_cast<String*>(nullptr); // Non-virtual destructor, with size.
|
delete static_cast<String*>(nullptr); // Non-virtual destructor, with size.
|
||||||
delete static_cast<SizedDealloc*>(nullptr); // No destructor, with size.
|
delete static_cast<SizedDealloc*>(nullptr); // No destructor, with size.
|
||||||
|
delete static_cast<DestroyingDealloc*>(nullptr); // No destructor, with destroying delete.
|
||||||
delete static_cast<Overaligned*>(nullptr); // No destructor, with size and alignment.
|
delete static_cast<Overaligned*>(nullptr); // No destructor, with size and alignment.
|
||||||
delete static_cast<PolymorphicBase*>(nullptr); // Virtual destructor
|
delete static_cast<PolymorphicBase*>(nullptr); // Virtual destructor
|
||||||
delete static_cast<const String*>(nullptr); // Pointer to const
|
delete static_cast<const String*>(nullptr); // Pointer to const
|
||||||
@@ -103,11 +114,20 @@ struct alignas(128) FailedInitOveraligned {
|
|||||||
void operator delete[](void*, std::align_val_t, float); // Aligned placement
|
void operator delete[](void*, std::align_val_t, float); // Aligned placement
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct alignas(128) FailedInitDestroyingDelete {
|
||||||
|
FailedInitDestroyingDelete();
|
||||||
|
~FailedInitDestroyingDelete();
|
||||||
|
|
||||||
|
void* operator new(size_t); // Non-placement
|
||||||
|
void operator delete(FailedInitDestroyingDelete*, std::destroying_delete_t); // Destroying delete
|
||||||
|
};
|
||||||
|
|
||||||
void TestFailedInit(int n) {
|
void TestFailedInit(int n) {
|
||||||
new FailedInit();
|
new FailedInit();
|
||||||
new FailedInit[n];
|
new FailedInit[n];
|
||||||
new(1.0f) FailedInitOveraligned();
|
new(1.0f) FailedInitOveraligned();
|
||||||
new(1.0f) FailedInitOveraligned[10];
|
new(1.0f) FailedInitOveraligned[10];
|
||||||
|
new FailedInitDestroyingDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- non-allocating placement new ---
|
// --- non-allocating placement new ---
|
||||||
|
|||||||
@@ -1,118 +1,123 @@
|
|||||||
newExprs
|
newExprs
|
||||||
| allocators.cpp:49:3:49:9 | new | int | void* operator new(unsigned long) | 4 | 4 | | |
|
| allocators.cpp:59:3:59:9 | new | int | void* operator new(unsigned long) | 4 | 4 | | |
|
||||||
| allocators.cpp:50:3:50:15 | new | int | void* operator new(size_t, float) | 4 | 4 | | |
|
| allocators.cpp:60:3:60:15 | new | int | void* operator new(size_t, float) | 4 | 4 | | |
|
||||||
| allocators.cpp:51:3:51:11 | new | int | void* operator new(unsigned long) | 4 | 4 | | |
|
| allocators.cpp:61:3:61:11 | new | int | void* operator new(unsigned long) | 4 | 4 | | |
|
||||||
| allocators.cpp:52:3:52:14 | new | String | void* operator new(unsigned long) | 8 | 8 | | |
|
| allocators.cpp:62:3:62:14 | new | String | void* operator new(unsigned long) | 8 | 8 | | |
|
||||||
| allocators.cpp:53:3:53:27 | new | String | void* operator new(size_t, float) | 8 | 8 | | |
|
| allocators.cpp:63:3:63:27 | new | String | void* operator new(size_t, float) | 8 | 8 | | |
|
||||||
| allocators.cpp:54:3:54:17 | new | Overaligned | void* operator new(unsigned long, std::align_val_t) | 256 | 128 | aligned | |
|
| allocators.cpp:64:3:64:17 | new | Overaligned | void* operator new(unsigned long, std::align_val_t) | 256 | 128 | aligned | |
|
||||||
| allocators.cpp:55:3:55:25 | new | Overaligned | void* operator new(size_t, std::align_val_t, float) | 256 | 128 | aligned | |
|
| allocators.cpp:65:3:65:25 | new | Overaligned | void* operator new(size_t, std::align_val_t, float) | 256 | 128 | aligned | |
|
||||||
| allocators.cpp:107:3:107:18 | new | FailedInit | void* FailedInit::operator new(size_t) | 1 | 1 | | |
|
| allocators.cpp:126:3:126:18 | new | FailedInit | void* FailedInit::operator new(size_t) | 1 | 1 | | |
|
||||||
| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | void* FailedInitOveraligned::operator new(size_t, std::align_val_t, float) | 128 | 128 | aligned | |
|
| allocators.cpp:128:3:128:35 | new | FailedInitOveraligned | void* FailedInitOveraligned::operator new(size_t, std::align_val_t, float) | 128 | 128 | aligned | |
|
||||||
| allocators.cpp:129:3:129:21 | new | int | void* operator new(std::size_t, void*) | 4 | 4 | | & ... |
|
| allocators.cpp:130:3:130:34 | new | FailedInitDestroyingDelete | void* FailedInitDestroyingDelete::operator new(size_t) | 128 | 128 | | |
|
||||||
| allocators.cpp:135:3:135:26 | new | int | void* operator new(std::size_t, std::nothrow_t const&) | 4 | 4 | | |
|
| allocators.cpp:149:3:149:21 | new | int | void* operator new(std::size_t, void*) | 4 | 4 | | & ... |
|
||||||
|
| allocators.cpp:155:3:155:26 | new | int | void* operator new(std::size_t, std::nothrow_t const&) | 4 | 4 | | |
|
||||||
newArrayExprs
|
newArrayExprs
|
||||||
| allocators.cpp:68:3:68:12 | new[] | int[] | int | void* operator new[](unsigned long) | 4 | 4 | | n | |
|
| allocators.cpp:79:3:79:12 | new[] | int[] | int | void* operator new[](unsigned long) | 4 | 4 | | n | |
|
||||||
| allocators.cpp:69:3:69:18 | new[] | int[] | int | void* operator new[](size_t, float) | 4 | 4 | | n | |
|
| allocators.cpp:80:3:80:18 | new[] | int[] | int | void* operator new[](size_t, float) | 4 | 4 | | n | |
|
||||||
| allocators.cpp:70:3:70:15 | new[] | String[] | String | void* operator new[](unsigned long) | 8 | 8 | | n | |
|
| allocators.cpp:81:3:81:15 | new[] | String[] | String | void* operator new[](unsigned long) | 8 | 8 | | n | |
|
||||||
| allocators.cpp:71:3:71:20 | new[] | Overaligned[] | Overaligned | void* operator new[](unsigned long, std::align_val_t) | 256 | 128 | aligned | n | |
|
| allocators.cpp:82:3:82:20 | new[] | Overaligned[] | Overaligned | void* operator new[](unsigned long, std::align_val_t) | 256 | 128 | aligned | n | |
|
||||||
| allocators.cpp:72:3:72:16 | new[] | String[10] | String | void* operator new[](unsigned long) | 8 | 8 | | | |
|
| allocators.cpp:83:3:83:16 | new[] | String[10] | String | void* operator new[](unsigned long) | 8 | 8 | | | |
|
||||||
| allocators.cpp:108:3:108:19 | new[] | FailedInit[] | FailedInit | void* FailedInit::operator new[](size_t) | 1 | 1 | | n | |
|
| allocators.cpp:127:3:127:19 | new[] | FailedInit[] | FailedInit | void* FailedInit::operator new[](size_t) | 1 | 1 | | n | |
|
||||||
| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | void* FailedInitOveraligned::operator new[](size_t, std::align_val_t, float) | 128 | 128 | aligned | | |
|
| allocators.cpp:129:3:129:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | void* FailedInitOveraligned::operator new[](size_t, std::align_val_t, float) | 128 | 128 | aligned | | |
|
||||||
| allocators.cpp:132:3:132:17 | new[] | int[1] | int | void* operator new[](std::size_t, void*) | 4 | 4 | | | buf |
|
| allocators.cpp:152:3:152:17 | new[] | int[1] | int | void* operator new[](std::size_t, void*) | 4 | 4 | | | buf |
|
||||||
| allocators.cpp:136:3:136:26 | new[] | int[2] | int | void* operator new[](std::size_t, std::nothrow_t const&) | 4 | 4 | | | |
|
| allocators.cpp:156:3:156:26 | new[] | int[2] | int | void* operator new[](std::size_t, std::nothrow_t const&) | 4 | 4 | | | |
|
||||||
| allocators.cpp:142:13:142:27 | new[] | char[][10] | char[10] | void* operator new[](unsigned long) | 10 | 1 | | x | |
|
| allocators.cpp:162:13:162:27 | new[] | char[][10] | char[10] | void* operator new[](unsigned long) | 10 | 1 | | x | |
|
||||||
| allocators.cpp:143:13:143:28 | new[] | char[20][20] | char[20] | void* operator new[](unsigned long) | 20 | 1 | | | |
|
| allocators.cpp:163:13:163:28 | new[] | char[20][20] | char[20] | void* operator new[](unsigned long) | 20 | 1 | | | |
|
||||||
| allocators.cpp:144:13:144:31 | new[] | char[][30][30] | char[30][30] | void* operator new[](unsigned long) | 900 | 1 | | x | |
|
| allocators.cpp:164:13:164:31 | new[] | char[][30][30] | char[30][30] | void* operator new[](unsigned long) | 900 | 1 | | x | |
|
||||||
newExprDeallocators
|
newExprDeallocators
|
||||||
| allocators.cpp:52:3:52:14 | new | String | void operator delete(void*, unsigned long) | 8 | 8 | sized |
|
| allocators.cpp:62:3:62:14 | new | String | void operator delete(void*, unsigned long) | 8 | 8 | sized |
|
||||||
| allocators.cpp:53:3:53:27 | new | String | void operator delete(void*, float) | 8 | 8 | |
|
| allocators.cpp:63:3:63:27 | new | String | void operator delete(void*, float) | 8 | 8 | |
|
||||||
| allocators.cpp:107:3:107:18 | new | FailedInit | void FailedInit::operator delete(void*, size_t) | 1 | 1 | sized |
|
| allocators.cpp:126:3:126:18 | new | FailedInit | void FailedInit::operator delete(void*, size_t) | 1 | 1 | sized |
|
||||||
| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | void FailedInitOveraligned::operator delete(void*, std::align_val_t, float) | 128 | 128 | aligned |
|
| allocators.cpp:128:3:128:35 | new | FailedInitOveraligned | void FailedInitOveraligned::operator delete(void*, std::align_val_t, float) | 128 | 128 | aligned |
|
||||||
|
| allocators.cpp:130:3:130:34 | new | FailedInitDestroyingDelete | void FailedInitDestroyingDelete::operator delete(FailedInitDestroyingDelete*, std::destroying_delete_t) | 128 | 128 | destroying |
|
||||||
newArrayExprDeallocators
|
newArrayExprDeallocators
|
||||||
| allocators.cpp:70:3:70:15 | new[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
|
| allocators.cpp:81:3:81:15 | new[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
|
||||||
| allocators.cpp:72:3:72:16 | new[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
|
| allocators.cpp:83:3:83:16 | new[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
|
||||||
| allocators.cpp:108:3:108:19 | new[] | FailedInit | void FailedInit::operator delete[](void*, size_t) | 1 | 1 | sized |
|
| allocators.cpp:127:3:127:19 | new[] | FailedInit | void FailedInit::operator delete[](void*, size_t) | 1 | 1 | sized |
|
||||||
| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned | void FailedInitOveraligned::operator delete[](void*, std::align_val_t, float) | 128 | 128 | aligned |
|
| allocators.cpp:129:3:129:37 | new[] | FailedInitOveraligned | void FailedInitOveraligned::operator delete[](void*, std::align_val_t, float) | 128 | 128 | aligned |
|
||||||
deleteExprs
|
deleteExprs
|
||||||
| allocators.cpp:59:3:59:35 | delete | int | void operator delete(void*, unsigned long) | 4 | 4 | sized | false |
|
| allocators.cpp:69:3:69:35 | delete | int | void operator delete(void*, unsigned long) | 4 | 4 | sized | false |
|
||||||
| allocators.cpp:60:3:60:38 | delete | String | void operator delete(void*, unsigned long) | 8 | 8 | sized | false |
|
| allocators.cpp:70:3:70:38 | delete | String | void operator delete(void*, unsigned long) | 8 | 8 | sized | false |
|
||||||
| allocators.cpp:61:3:61:44 | delete | SizedDealloc | void SizedDealloc::operator delete(void*, size_t) | 32 | 1 | sized | true |
|
| allocators.cpp:71:3:71:44 | delete | SizedDealloc | void SizedDealloc::operator delete(void*, size_t) | 32 | 1 | sized | true |
|
||||||
| allocators.cpp:62:3:62:43 | delete | Overaligned | void operator delete(void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned | false |
|
| allocators.cpp:72:3:72:49 | delete | DestroyingDealloc | void DestroyingDealloc::operator delete(DestroyingDealloc*, std::destroying_delete_t) | 1 | 1 | destroying | true |
|
||||||
| allocators.cpp:64:3:64:44 | delete | const String | void operator delete(void*, unsigned long) | 8 | 8 | sized | false |
|
| allocators.cpp:73:3:73:43 | delete | Overaligned | void operator delete(void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned | false |
|
||||||
|
| allocators.cpp:75:3:75:44 | delete | const String | void operator delete(void*, unsigned long) | 8 | 8 | sized | false |
|
||||||
deleteArrayExprs
|
deleteArrayExprs
|
||||||
| allocators.cpp:78:3:78:37 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized |
|
| allocators.cpp:89:3:89:37 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized |
|
||||||
| allocators.cpp:79:3:79:40 | delete[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
|
| allocators.cpp:90:3:90:40 | delete[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
|
||||||
| allocators.cpp:80:3:80:46 | delete[] | SizedDealloc | void SizedDealloc::operator delete[](void*, size_t) | 32 | 1 | sized |
|
| allocators.cpp:91:3:91:46 | delete[] | SizedDealloc | void SizedDealloc::operator delete[](void*, size_t) | 32 | 1 | sized |
|
||||||
| allocators.cpp:81:3:81:45 | delete[] | Overaligned | void operator delete[](void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned |
|
| allocators.cpp:92:3:92:45 | delete[] | Overaligned | void operator delete[](void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned |
|
||||||
| allocators.cpp:82:3:82:49 | delete[] | PolymorphicBase | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
|
| allocators.cpp:93:3:93:49 | delete[] | PolymorphicBase | void operator delete[](void*, unsigned long) | 8 | 8 | sized |
|
||||||
| allocators.cpp:83:3:83:23 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized |
|
| allocators.cpp:94:3:94:23 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized |
|
||||||
allocationFunctions
|
allocationFunctions
|
||||||
| allocators.cpp:7:7:7:18 | operator new | getSizeArg = 0, requiresDealloc |
|
| allocators.cpp:12:7:12:18 | operator new | getSizeArg = 0, requiresDealloc |
|
||||||
| allocators.cpp:8:7:8:20 | operator new[] | getSizeArg = 0, requiresDealloc |
|
| allocators.cpp:13:7:13:20 | operator new[] | getSizeArg = 0, requiresDealloc |
|
||||||
| allocators.cpp:9:7:9:18 | operator new | getSizeArg = 0, requiresDealloc |
|
| allocators.cpp:14:7:14:18 | operator new | getSizeArg = 0, requiresDealloc |
|
||||||
| allocators.cpp:10:7:10:20 | operator new[] | getSizeArg = 0, requiresDealloc |
|
| allocators.cpp:15:7:15:20 | operator new[] | getSizeArg = 0, requiresDealloc |
|
||||||
| allocators.cpp:121:7:121:18 | operator new | getPlacementArgument = 1, getSizeArg = 0 |
|
| allocators.cpp:141:7:141:18 | operator new | getPlacementArgument = 1, getSizeArg = 0 |
|
||||||
| allocators.cpp:122:7:122:20 | operator new[] | getPlacementArgument = 1, getSizeArg = 0 |
|
| allocators.cpp:142:7:142:20 | operator new[] | getPlacementArgument = 1, getSizeArg = 0 |
|
||||||
| allocators.cpp:123:7:123:18 | operator new | getSizeArg = 0, requiresDealloc |
|
| allocators.cpp:143:7:143:18 | operator new | getSizeArg = 0, requiresDealloc |
|
||||||
| allocators.cpp:124:7:124:20 | operator new[] | getSizeArg = 0, requiresDealloc |
|
| allocators.cpp:144:7:144:20 | operator new[] | getSizeArg = 0, requiresDealloc |
|
||||||
| allocators.cpp:153:7:153:12 | malloc | getSizeArg = 0, requiresDealloc |
|
| allocators.cpp:173:7:173:12 | malloc | getSizeArg = 0, requiresDealloc |
|
||||||
| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc |
|
| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc |
|
||||||
| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc |
|
| file://:0:0:0:0 | operator new | getSizeArg = 0, requiresDealloc |
|
||||||
| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc |
|
| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc |
|
||||||
| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc |
|
| file://:0:0:0:0 | operator new[] | getSizeArg = 0, requiresDealloc |
|
||||||
allocationExprs
|
allocationExprs
|
||||||
| allocators.cpp:49:3:49:9 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
|
| allocators.cpp:59:3:59:9 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
|
||||||
| allocators.cpp:50:3:50:15 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
|
| allocators.cpp:60:3:60:15 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
|
||||||
| allocators.cpp:51:3:51:11 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
|
| allocators.cpp:61:3:61:11 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
|
||||||
| allocators.cpp:52:3:52:14 | new | getAllocatedElementType = String, getSizeBytes = 8, requiresDealloc |
|
| allocators.cpp:62:3:62:14 | new | getAllocatedElementType = String, getSizeBytes = 8, requiresDealloc |
|
||||||
| allocators.cpp:53:3:53:27 | new | getAllocatedElementType = String, getSizeBytes = 8, requiresDealloc |
|
| allocators.cpp:63:3:63:27 | new | getAllocatedElementType = String, getSizeBytes = 8, requiresDealloc |
|
||||||
| allocators.cpp:54:3:54:17 | new | getAllocatedElementType = Overaligned, getSizeBytes = 256, requiresDealloc |
|
| allocators.cpp:64:3:64:17 | new | getAllocatedElementType = Overaligned, getSizeBytes = 256, requiresDealloc |
|
||||||
| allocators.cpp:55:3:55:25 | new | getAllocatedElementType = Overaligned, getSizeBytes = 256, requiresDealloc |
|
| allocators.cpp:65:3:65:25 | new | getAllocatedElementType = Overaligned, getSizeBytes = 256, requiresDealloc |
|
||||||
| allocators.cpp:68:3:68:12 | new[] | getAllocatedElementType = int, getSizeExpr = n, getSizeMult = 4, requiresDealloc |
|
| allocators.cpp:79:3:79:12 | new[] | getAllocatedElementType = int, getSizeExpr = n, getSizeMult = 4, requiresDealloc |
|
||||||
| allocators.cpp:69:3:69:18 | new[] | getAllocatedElementType = int, getSizeExpr = n, getSizeMult = 4, requiresDealloc |
|
| allocators.cpp:80:3:80:18 | new[] | getAllocatedElementType = int, getSizeExpr = n, getSizeMult = 4, requiresDealloc |
|
||||||
| allocators.cpp:70:3:70:15 | new[] | getAllocatedElementType = String, getSizeExpr = n, getSizeMult = 8, requiresDealloc |
|
| allocators.cpp:81:3:81:15 | new[] | getAllocatedElementType = String, getSizeExpr = n, getSizeMult = 8, requiresDealloc |
|
||||||
| allocators.cpp:71:3:71:20 | new[] | getAllocatedElementType = Overaligned, getSizeExpr = n, getSizeMult = 256, requiresDealloc |
|
| allocators.cpp:82:3:82:20 | new[] | getAllocatedElementType = Overaligned, getSizeExpr = n, getSizeMult = 256, requiresDealloc |
|
||||||
| allocators.cpp:72:3:72:16 | new[] | getAllocatedElementType = String, getSizeBytes = 80, requiresDealloc |
|
| allocators.cpp:83:3:83:16 | new[] | getAllocatedElementType = String, getSizeBytes = 80, requiresDealloc |
|
||||||
| allocators.cpp:107:3:107:18 | new | getAllocatedElementType = FailedInit, getSizeBytes = 1, requiresDealloc |
|
| allocators.cpp:126:3:126:18 | new | getAllocatedElementType = FailedInit, getSizeBytes = 1, requiresDealloc |
|
||||||
| allocators.cpp:108:3:108:19 | new[] | getAllocatedElementType = FailedInit, getSizeExpr = n, getSizeMult = 1, requiresDealloc |
|
| allocators.cpp:127:3:127:19 | new[] | getAllocatedElementType = FailedInit, getSizeExpr = n, getSizeMult = 1, requiresDealloc |
|
||||||
| allocators.cpp:109:3:109:35 | new | getAllocatedElementType = FailedInitOveraligned, getSizeBytes = 128, requiresDealloc |
|
| allocators.cpp:128:3:128:35 | new | getAllocatedElementType = FailedInitOveraligned, getSizeBytes = 128, requiresDealloc |
|
||||||
| allocators.cpp:110:3:110:37 | new[] | getAllocatedElementType = FailedInitOveraligned, getSizeBytes = 1280, requiresDealloc |
|
| allocators.cpp:129:3:129:37 | new[] | getAllocatedElementType = FailedInitOveraligned, getSizeBytes = 1280, requiresDealloc |
|
||||||
| allocators.cpp:129:3:129:21 | new | getAllocatedElementType = int, getSizeBytes = 4 |
|
| allocators.cpp:130:3:130:34 | new | getAllocatedElementType = FailedInitDestroyingDelete, getSizeBytes = 128, requiresDealloc |
|
||||||
| allocators.cpp:132:3:132:17 | new[] | getAllocatedElementType = int, getSizeBytes = 4 |
|
| allocators.cpp:149:3:149:21 | new | getAllocatedElementType = int, getSizeBytes = 4 |
|
||||||
| allocators.cpp:135:3:135:26 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
|
| allocators.cpp:152:3:152:17 | new[] | getAllocatedElementType = int, getSizeBytes = 4 |
|
||||||
| allocators.cpp:136:3:136:26 | new[] | getAllocatedElementType = int, getSizeBytes = 8, requiresDealloc |
|
| allocators.cpp:155:3:155:26 | new | getAllocatedElementType = int, getSizeBytes = 4, requiresDealloc |
|
||||||
| allocators.cpp:142:13:142:27 | new[] | getAllocatedElementType = char[10], getSizeExpr = x, getSizeMult = 10, requiresDealloc |
|
| allocators.cpp:156:3:156:26 | new[] | getAllocatedElementType = int, getSizeBytes = 8, requiresDealloc |
|
||||||
| allocators.cpp:143:13:143:28 | new[] | getAllocatedElementType = char[20], getSizeBytes = 400, requiresDealloc |
|
| allocators.cpp:162:13:162:27 | new[] | getAllocatedElementType = char[10], getSizeExpr = x, getSizeMult = 10, requiresDealloc |
|
||||||
| allocators.cpp:144:13:144:31 | new[] | getAllocatedElementType = char[30][30], getSizeExpr = x, getSizeMult = 900, requiresDealloc |
|
| allocators.cpp:163:13:163:28 | new[] | getAllocatedElementType = char[20], getSizeBytes = 400, requiresDealloc |
|
||||||
| allocators.cpp:149:8:149:19 | call to operator new | getSizeBytes = 4, getSizeExpr = sizeof(int), getSizeMult = 1, requiresDealloc |
|
| allocators.cpp:164:13:164:31 | new[] | getAllocatedElementType = char[30][30], getSizeExpr = x, getSizeMult = 900, requiresDealloc |
|
||||||
| allocators.cpp:157:50:157:55 | call to malloc | getAllocatedElementType = const volatile int, getSizeBytes = 5, getSizeExpr = 5, getSizeMult = 1, requiresDealloc |
|
| allocators.cpp:169:8:169:19 | call to operator new | getSizeBytes = 4, getSizeExpr = sizeof(int), getSizeMult = 1, requiresDealloc |
|
||||||
| allocators.cpp:158:26:158:31 | call to malloc | getAllocatedElementType = int, getSizeBytes = 20, getSizeExpr = 5, getSizeMult = 4, requiresDealloc |
|
| allocators.cpp:177:50:177:55 | call to malloc | getAllocatedElementType = const volatile int, getSizeBytes = 5, getSizeExpr = 5, getSizeMult = 1, requiresDealloc |
|
||||||
| allocators.cpp:159:31:159:36 | call to malloc | getAllocatedElementType = volatile long, getSizeExpr = count, getSizeMult = 1, requiresDealloc |
|
| allocators.cpp:178:26:178:31 | call to malloc | getAllocatedElementType = int, getSizeBytes = 20, getSizeExpr = 5, getSizeMult = 4, requiresDealloc |
|
||||||
| allocators.cpp:160:16:160:21 | call to malloc | getAllocatedElementType = volatile long, getSizeExpr = count, getSizeMult = 4, requiresDealloc |
|
| allocators.cpp:179:31:179:36 | call to malloc | getAllocatedElementType = volatile long, getSizeExpr = count, getSizeMult = 1, requiresDealloc |
|
||||||
| allocators.cpp:161:34:161:39 | call to malloc | getAllocatedElementType = const char, getSizeExpr = ... + ..., getSizeMult = 1, requiresDealloc |
|
| allocators.cpp:180:16:180:21 | call to malloc | getAllocatedElementType = volatile long, getSizeExpr = count, getSizeMult = 4, requiresDealloc |
|
||||||
| allocators.cpp:162:23:162:28 | call to malloc | getSizeExpr = count, getSizeMult = 8, requiresDealloc |
|
| allocators.cpp:181:34:181:39 | call to malloc | getAllocatedElementType = const char, getSizeExpr = ... + ..., getSizeMult = 1, requiresDealloc |
|
||||||
| allocators.cpp:163:3:163:8 | call to malloc | getSizeBytes = 32, getSizeExpr = ... * ..., getSizeMult = 1, requiresDealloc |
|
| allocators.cpp:182:23:182:28 | call to malloc | getSizeExpr = count, getSizeMult = 8, requiresDealloc |
|
||||||
|
| allocators.cpp:183:3:183:8 | call to malloc | getSizeBytes = 32, getSizeExpr = ... * ..., getSizeMult = 1, requiresDealloc |
|
||||||
deallocationFunctions
|
deallocationFunctions
|
||||||
| allocators.cpp:11:6:11:20 | operator delete | getFreedArg = 0 |
|
| allocators.cpp:16:6:16:20 | operator delete | getFreedArg = 0 |
|
||||||
| allocators.cpp:12:6:12:22 | operator delete[] | getFreedArg = 0 |
|
| allocators.cpp:17:6:17:22 | operator delete[] | getFreedArg = 0 |
|
||||||
| allocators.cpp:13:6:13:20 | operator delete | getFreedArg = 0 |
|
| allocators.cpp:18:6:18:20 | operator delete | getFreedArg = 0 |
|
||||||
| allocators.cpp:14:6:14:22 | operator delete[] | getFreedArg = 0 |
|
| allocators.cpp:19:6:19:22 | operator delete[] | getFreedArg = 0 |
|
||||||
| file://:0:0:0:0 | operator delete | getFreedArg = 0 |
|
| file://:0:0:0:0 | operator delete | getFreedArg = 0 |
|
||||||
| file://:0:0:0:0 | operator delete | getFreedArg = 0 |
|
| file://:0:0:0:0 | operator delete | getFreedArg = 0 |
|
||||||
| file://:0:0:0:0 | operator delete | getFreedArg = 0 |
|
| file://:0:0:0:0 | operator delete | getFreedArg = 0 |
|
||||||
| file://:0:0:0:0 | operator delete[] | getFreedArg = 0 |
|
| file://:0:0:0:0 | operator delete[] | getFreedArg = 0 |
|
||||||
| file://:0:0:0:0 | operator delete[] | getFreedArg = 0 |
|
| file://:0:0:0:0 | operator delete[] | getFreedArg = 0 |
|
||||||
deallocationExprs
|
deallocationExprs
|
||||||
| allocators.cpp:59:3:59:35 | delete | getFreedExpr = 0 |
|
| allocators.cpp:69:3:69:35 | delete | getFreedExpr = 0 |
|
||||||
| allocators.cpp:60:3:60:38 | delete | getFreedExpr = 0 |
|
| allocators.cpp:70:3:70:38 | delete | getFreedExpr = 0 |
|
||||||
| allocators.cpp:61:3:61:44 | delete | getFreedExpr = 0 |
|
| allocators.cpp:71:3:71:44 | delete | getFreedExpr = 0 |
|
||||||
| allocators.cpp:62:3:62:43 | delete | getFreedExpr = 0 |
|
| allocators.cpp:72:3:72:49 | delete | getFreedExpr = 0 |
|
||||||
| allocators.cpp:63:3:63:47 | delete | getFreedExpr = 0 |
|
| allocators.cpp:73:3:73:43 | delete | getFreedExpr = 0 |
|
||||||
| allocators.cpp:64:3:64:44 | delete | getFreedExpr = 0 |
|
| allocators.cpp:74:3:74:47 | delete | getFreedExpr = 0 |
|
||||||
| allocators.cpp:78:3:78:37 | delete[] | getFreedExpr = 0 |
|
| allocators.cpp:75:3:75:44 | delete | getFreedExpr = 0 |
|
||||||
| allocators.cpp:79:3:79:40 | delete[] | getFreedExpr = 0 |
|
| allocators.cpp:89:3:89:37 | delete[] | getFreedExpr = 0 |
|
||||||
| allocators.cpp:80:3:80:46 | delete[] | getFreedExpr = 0 |
|
| allocators.cpp:90:3:90:40 | delete[] | getFreedExpr = 0 |
|
||||||
| allocators.cpp:81:3:81:45 | delete[] | getFreedExpr = 0 |
|
| allocators.cpp:91:3:91:46 | delete[] | getFreedExpr = 0 |
|
||||||
| allocators.cpp:82:3:82:49 | delete[] | getFreedExpr = 0 |
|
| allocators.cpp:92:3:92:45 | delete[] | getFreedExpr = 0 |
|
||||||
| allocators.cpp:83:3:83:23 | delete[] | getFreedExpr = call to GetPointer |
|
| allocators.cpp:93:3:93:49 | delete[] | getFreedExpr = 0 |
|
||||||
| allocators.cpp:150:2:150:16 | call to operator delete | getFreedExpr = ptr |
|
| allocators.cpp:94:3:94:23 | delete[] | getFreedExpr = call to GetPointer |
|
||||||
|
| allocators.cpp:170:2:170:16 | call to operator delete | getFreedExpr = ptr |
|
||||||
|
|||||||
@@ -50,10 +50,11 @@ query predicate newExprDeallocators(
|
|||||||
type = allocatedType.toString() and
|
type = allocatedType.toString() and
|
||||||
size = allocatedType.getSize() and
|
size = allocatedType.getSize() and
|
||||||
alignment = allocatedType.getAlignment() and
|
alignment = allocatedType.getAlignment() and
|
||||||
exists(string sized, string aligned |
|
exists(string sized, string aligned, string destroying |
|
||||||
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
|
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
|
||||||
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
|
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
|
||||||
form = sized + " " + aligned
|
(if expr.isDestroyingDeleteDeallocation() then destroying = "destroying" else destroying = "") and
|
||||||
|
form = sized + " " + aligned + " " + destroying
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -68,10 +69,11 @@ query predicate newArrayExprDeallocators(
|
|||||||
type = elementType.toString() and
|
type = elementType.toString() and
|
||||||
size = elementType.getSize() and
|
size = elementType.getSize() and
|
||||||
alignment = elementType.getAlignment() and
|
alignment = elementType.getAlignment() and
|
||||||
exists(string sized, string aligned |
|
exists(string sized, string aligned, string destroying |
|
||||||
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
|
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
|
||||||
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
|
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
|
||||||
form = sized + " " + aligned
|
(if expr.isDestroyingDeleteDeallocation() then destroying = "destroying" else destroying = "") and
|
||||||
|
form = sized + " " + aligned + " " + destroying
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -87,10 +89,11 @@ query predicate deleteExprs(
|
|||||||
type = deletedType.toString() and
|
type = deletedType.toString() and
|
||||||
size = deletedType.getSize() and
|
size = deletedType.getSize() and
|
||||||
alignment = deletedType.getAlignment() and
|
alignment = deletedType.getAlignment() and
|
||||||
exists(string sized, string aligned |
|
exists(string sized, string aligned, string destroying |
|
||||||
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
|
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
|
||||||
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
|
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
|
||||||
form = sized + " " + aligned
|
(if expr.isDestroyingDeleteDeallocation() then destroying = "destroying" else destroying = "") and
|
||||||
|
form = sized + " " + aligned + " " + destroying
|
||||||
) and
|
) and
|
||||||
if exists(expr.getDeallocatorCall())
|
if exists(expr.getDeallocatorCall())
|
||||||
then hasDeallocatorCall = true
|
then hasDeallocatorCall = true
|
||||||
@@ -108,10 +111,11 @@ query predicate deleteArrayExprs(
|
|||||||
type = elementType.toString() and
|
type = elementType.toString() and
|
||||||
size = elementType.getSize() and
|
size = elementType.getSize() and
|
||||||
alignment = elementType.getAlignment() and
|
alignment = elementType.getAlignment() and
|
||||||
exists(string sized, string aligned |
|
exists(string sized, string aligned, string destroying |
|
||||||
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
|
(if expr.hasAlignedDeallocation() then aligned = "aligned" else aligned = "") and
|
||||||
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
|
(if expr.hasSizedDeallocation() then sized = "sized" else sized = "") and
|
||||||
form = sized + " " + aligned
|
(if expr.isDestroyingDeleteDeallocation() then destroying = "destroying" else destroying = "") and
|
||||||
|
form = sized + " " + aligned + " " + destroying
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
| declspec.cpp:4:23:4:43 | Use fatal() instead | declspec.cpp:4:59:4:62 | exit | declspec.cpp:4:12:4:21 | deprecated | Use fatal() instead |
|
| declspec.cpp:4:23:4:43 | Use fatal() instead | declspec.cpp:4:59:4:62 | exit | declspec.cpp:4:12:4:21 | deprecated | Use fatal() instead |
|
||||||
| routine_attributes2.cpp:5:6:5:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility | hidden |
|
| routine_attributes2.cpp:5:6:5:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility | hidden |
|
||||||
| routine_attributes2.cpp:5:6:5:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility | hidden |
|
|
||||||
| routine_attributes2.h:3:6:3:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility | hidden |
|
|
||||||
| routine_attributes2.h:3:6:3:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility | hidden |
|
| routine_attributes2.h:3:6:3:11 | hidden | routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility | hidden |
|
||||||
| routine_attributes.c:3:53:3:59 | dummy | routine_attributes.c:3:12:3:24 | named_weakref | routine_attributes.c:3:44:3:50 | weakref | dummy |
|
| routine_attributes.c:3:53:3:59 | dummy | routine_attributes.c:3:12:3:24 | named_weakref | routine_attributes.c:3:44:3:50 | weakref | dummy |
|
||||||
| routine_attributes.c:4:62:4:68 | dummy | routine_attributes.c:4:12:4:26 | aliased_weakref | routine_attributes.c:4:55:4:59 | alias | dummy |
|
| routine_attributes.c:4:62:4:68 | dummy | routine_attributes.c:4:12:4:26 | aliased_weakref | routine_attributes.c:4:55:4:59 | alias | dummy |
|
||||||
|
|||||||
@@ -19,8 +19,6 @@
|
|||||||
| header_export.cpp:18:6:18:16 | myFunction5 | header.h:10:2:10:10 | dllexport |
|
| header_export.cpp:18:6:18:16 | myFunction5 | header.h:10:2:10:10 | dllexport |
|
||||||
| header_export.cpp:18:6:18:16 | myFunction5 | header.h:10:2:10:10 | dllimport |
|
| header_export.cpp:18:6:18:16 | myFunction5 | header.h:10:2:10:10 | dllimport |
|
||||||
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility |
|
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility |
|
||||||
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.cpp:5:6:5:11 | visibility |
|
|
||||||
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility |
|
|
||||||
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility |
|
| routine_attributes2.cpp:5:13:5:21 | a_routine | routine_attributes2.h:3:6:3:11 | visibility |
|
||||||
| routine_attributes.c:3:12:3:24 | named_weakref | routine_attributes.c:3:44:3:50 | weakref |
|
| routine_attributes.c:3:12:3:24 | named_weakref | routine_attributes.c:3:44:3:50 | weakref |
|
||||||
| routine_attributes.c:4:12:4:26 | aliased_weakref | routine_attributes.c:4:46:4:52 | weakref |
|
| routine_attributes.c:4:12:4:26 | aliased_weakref | routine_attributes.c:4:46:4:52 | weakref |
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.cpp:5:7:5:12 | visibility | type_attributes2.cpp:5:7:5:12 | hidden |
|
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.cpp:5:7:5:12 | visibility | type_attributes2.cpp:5:7:5:12 | hidden |
|
||||||
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility | type_attributes2.h:3:7:3:12 | hidden |
|
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility | type_attributes2.h:3:7:3:12 | hidden |
|
||||||
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility | type_attributes2.h:3:7:3:12 | hidden |
|
|
||||||
| type_attributes_ms.cpp:4:67:4:75 | IDispatch | type_attributes_ms.cpp:4:19:4:22 | uuid | type_attributes_ms.cpp:4:24:4:63 | {00020400-0000-0000-c000-000000000046} |
|
| type_attributes_ms.cpp:4:67:4:75 | IDispatch | type_attributes_ms.cpp:4:19:4:22 | uuid | type_attributes_ms.cpp:4:24:4:63 | {00020400-0000-0000-c000-000000000046} |
|
||||||
| type_attributes_ms.cpp:5:30:5:33 | Str1 | type_attributes_ms.cpp:5:12:5:16 | align | type_attributes_ms.cpp:5:18:5:19 | 32 |
|
| type_attributes_ms.cpp:5:30:5:33 | Str1 | type_attributes_ms.cpp:5:12:5:16 | align | type_attributes_ms.cpp:5:18:5:19 | 32 |
|
||||||
| type_attributes_ms.cpp:6:55:6:62 | IUnknown | type_attributes_ms.cpp:6:2:6:2 | uuid | type_attributes_ms.cpp:6:2:6:2 | 00000000-0000-0000-c000-000000000046 |
|
| type_attributes_ms.cpp:6:55:6:62 | IUnknown | type_attributes_ms.cpp:6:2:6:2 | uuid | type_attributes_ms.cpp:6:2:6:2 | 00000000-0000-0000-c000-000000000046 |
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
| file://:0:0:0:0 | short __attribute((__may_alias__)) | type_attributes.c:25:30:25:42 | may_alias |
|
| file://:0:0:0:0 | short __attribute((__may_alias__)) | type_attributes.c:25:30:25:42 | may_alias |
|
||||||
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.cpp:5:7:5:12 | visibility |
|
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.cpp:5:7:5:12 | visibility |
|
||||||
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility |
|
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility |
|
||||||
| type_attributes2.cpp:5:14:5:20 | a_class | type_attributes2.h:3:7:3:12 | visibility |
|
|
||||||
| type_attributes.c:5:36:5:51 | my_packed_struct | type_attributes.c:5:23:5:32 | packed |
|
| type_attributes.c:5:36:5:51 | my_packed_struct | type_attributes.c:5:23:5:32 | packed |
|
||||||
| type_attributes.c:10:54:10:54 | (unnamed class/struct/union) | type_attributes.c:10:30:10:50 | transparent_union |
|
| type_attributes.c:10:54:10:54 | (unnamed class/struct/union) | type_attributes.c:10:30:10:50 | transparent_union |
|
||||||
| type_attributes.c:16:54:16:54 | (unnamed class/struct/union) | type_attributes.c:16:30:16:50 | transparent_union |
|
| type_attributes.c:16:54:16:54 | (unnamed class/struct/union) | type_attributes.c:16:30:16:50 | transparent_union |
|
||||||
|
|||||||
@@ -7,8 +7,6 @@
|
|||||||
| ms_var_attributes.cpp:20:34:20:37 | pBuf | ms_var_attributes.cpp:20:12:20:12 | SAL_volatile |
|
| ms_var_attributes.cpp:20:34:20:37 | pBuf | ms_var_attributes.cpp:20:12:20:12 | SAL_volatile |
|
||||||
| ms_var_attributes.h:5:22:5:27 | myInt3 | ms_var_attributes.h:5:1:5:9 | dllexport |
|
| ms_var_attributes.h:5:22:5:27 | myInt3 | ms_var_attributes.h:5:1:5:9 | dllexport |
|
||||||
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.cpp:5:5:5:10 | visibility |
|
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.cpp:5:5:5:10 | visibility |
|
||||||
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.cpp:5:5:5:10 | visibility |
|
|
||||||
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.h:3:12:3:17 | visibility |
|
|
||||||
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.h:3:12:3:17 | visibility |
|
| var_attributes2.cpp:5:12:5:21 | a_variable | var_attributes2.h:3:12:3:17 | visibility |
|
||||||
| var_attributes.c:1:12:1:19 | weak_var | var_attributes.c:1:36:1:39 | weak |
|
| var_attributes.c:1:12:1:19 | weak_var | var_attributes.c:1:36:1:39 | weak |
|
||||||
| var_attributes.c:2:12:2:22 | weakref_var | var_attributes.c:2:39:2:45 | weakref |
|
| var_attributes.c:2:12:2:22 | weakref_var | var_attributes.c:2:39:2:45 | weakref |
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
| Dubious signature "(const_iterator,size_type,const T &)" in summary model. |
|
| Dubious signature "(const_iterator,size_type,const T &)" in summary model. |
|
||||||
| Dubious signature "(deque &&)" in summary model. |
|
| Dubious signature "(deque &&)" in summary model. |
|
||||||
| Dubious signature "(deque &&,const Allocator &)" in summary model. |
|
| Dubious signature "(deque &&,const Allocator &)" in summary model. |
|
||||||
|
| Dubious signature "(format_string,Args &&)" in summary model. |
|
||||||
| Dubious signature "(forward_list &&)" in summary model. |
|
| Dubious signature "(forward_list &&)" in summary model. |
|
||||||
| Dubious signature "(forward_list &&,const Allocator &)" in summary model. |
|
| Dubious signature "(forward_list &&,const Allocator &)" in summary model. |
|
||||||
| Dubious signature "(list &&)" in summary model. |
|
| Dubious signature "(list &&)" in summary model. |
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
|
#include "stl.h"
|
||||||
typedef unsigned long size_t;
|
typedef unsigned long size_t;
|
||||||
typedef struct {} FILE;
|
typedef struct {} FILE;
|
||||||
|
|
||||||
@@ -157,3 +157,11 @@ void test2()
|
|||||||
sink(s[strlen(s) - 1]); // $ ast,ir
|
sink(s[strlen(s) - 1]); // $ ast,ir
|
||||||
sink(ws + (wcslen(ws) / 2)); // $ ast,ir
|
sink(ws + (wcslen(ws) / 2)); // $ ast,ir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_format() {
|
||||||
|
auto s = std::format("{}", string::source());
|
||||||
|
sink(s); // $ ir MISSING: ast
|
||||||
|
|
||||||
|
auto s2 = std::format(string::source());
|
||||||
|
sink(s2); // $ ir MISSING: ast
|
||||||
|
}
|
||||||
@@ -447,6 +447,10 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
|
|||||||
| format.cpp:158:13:158:18 | call to wcslen | format.cpp:158:13:158:26 | ... / ... | TAINT |
|
| format.cpp:158:13:158:18 | call to wcslen | format.cpp:158:13:158:26 | ... / ... | TAINT |
|
||||||
| format.cpp:158:13:158:26 | ... / ... | format.cpp:158:7:158:27 | ... + ... | TAINT |
|
| format.cpp:158:13:158:26 | ... / ... | format.cpp:158:7:158:27 | ... + ... | TAINT |
|
||||||
| format.cpp:158:26:158:26 | 2 | format.cpp:158:13:158:26 | ... / ... | TAINT |
|
| format.cpp:158:26:158:26 | 2 | format.cpp:158:13:158:26 | ... / ... | TAINT |
|
||||||
|
| format.cpp:162:12:162:22 | call to format | format.cpp:163:8:163:8 | s | |
|
||||||
|
| format.cpp:162:24:162:27 | {} | format.cpp:162:24:162:27 | call to basic_format_string | TAINT |
|
||||||
|
| format.cpp:165:13:165:23 | call to format | format.cpp:166:8:166:9 | s2 | |
|
||||||
|
| format.cpp:165:25:165:38 | call to source | format.cpp:165:25:165:40 | call to basic_format_string | TAINT |
|
||||||
| map.cpp:21:28:21:28 | call to pair | map.cpp:23:2:23:2 | a | |
|
| map.cpp:21:28:21:28 | call to pair | map.cpp:23:2:23:2 | a | |
|
||||||
| map.cpp:21:28:21:28 | call to pair | map.cpp:24:7:24:7 | a | |
|
| map.cpp:21:28:21:28 | call to pair | map.cpp:24:7:24:7 | a | |
|
||||||
| map.cpp:21:28:21:28 | call to pair | map.cpp:25:7:25:7 | a | |
|
| map.cpp:21:28:21:28 | call to pair | map.cpp:25:7:25:7 | a | |
|
||||||
|
|||||||
@@ -642,3 +642,38 @@ namespace std {
|
|||||||
pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
|
pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- string view ---
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template<class CharT, class Traits = char_traits<CharT>>
|
||||||
|
class basic_string_view {
|
||||||
|
public:
|
||||||
|
using size_type = size_t;
|
||||||
|
|
||||||
|
basic_string_view() noexcept;
|
||||||
|
basic_string_view(const basic_string_view&) noexcept;
|
||||||
|
basic_string_view(const CharT*, size_type);
|
||||||
|
basic_string_view(const CharT*);
|
||||||
|
template<class It, class End> basic_string_view(It, End);
|
||||||
|
template<class R> explicit basic_string_view(R&&);
|
||||||
|
basic_string_view& operator=(const basic_string_view&) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
using string_view = basic_string_view<char>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- format ---
|
||||||
|
namespace std {
|
||||||
|
template<class CharT /* class... Args */>
|
||||||
|
struct basic_format_string {
|
||||||
|
public:
|
||||||
|
template<class T> basic_format_string(const T&);
|
||||||
|
|
||||||
|
basic_string_view<CharT> get() const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
using format_string = basic_format_string<char>; // simplified from `char, std::type_identity_t<Args>...`
|
||||||
|
|
||||||
|
template<class... Args> string format( format_string fmt, Args&&... args );
|
||||||
|
}
|
||||||
@@ -27,6 +27,10 @@ signatureMatches
|
|||||||
| stl.h:190:17:190:23 | replace | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 0 |
|
| stl.h:190:17:190:23 | replace | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 0 |
|
||||||
| stl.h:190:17:190:23 | replace | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 1 |
|
| stl.h:190:17:190:23 | replace | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 1 |
|
||||||
| stl.h:190:17:190:23 | replace | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 |
|
| stl.h:190:17:190:23 | replace | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 |
|
||||||
|
| stl.h:232:84:232:90 | getline | (const_iterator,InputIt,InputIt) | deque | insert<InputIt> | 2 |
|
||||||
|
| stl.h:232:84:232:90 | getline | (const_iterator,InputIt,InputIt) | forward_list | insert_after<InputIt> | 2 |
|
||||||
|
| stl.h:232:84:232:90 | getline | (const_iterator,InputIt,InputIt) | list | insert<InputIt> | 2 |
|
||||||
|
| stl.h:232:84:232:90 | getline | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 |
|
||||||
| stl.h:294:12:294:17 | vector | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
|
| stl.h:294:12:294:17 | vector | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
|
||||||
| stl.h:294:12:294:17 | vector | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
|
| stl.h:294:12:294:17 | vector | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
|
||||||
| stl.h:294:12:294:17 | vector | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
|
| stl.h:294:12:294:17 | vector | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
|
||||||
@@ -175,6 +179,7 @@ signatureMatches
|
|||||||
| stl.h:333:42:333:47 | insert | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 1 |
|
| stl.h:333:42:333:47 | insert | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 1 |
|
||||||
| stl.h:333:42:333:47 | insert | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 |
|
| stl.h:333:42:333:47 | insert | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 |
|
||||||
| stl.h:333:42:333:47 | insert | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 |
|
| stl.h:333:42:333:47 | insert | (const_iterator,InputIt,InputIt) | vector | insert<InputIt> | 2 |
|
||||||
|
| stl.h:335:37:335:43 | emplace | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
| stl.h:396:3:396:3 | pair | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
|
| stl.h:396:3:396:3 | pair | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
|
||||||
| stl.h:396:3:396:3 | pair | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
|
| stl.h:396:3:396:3 | pair | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
|
||||||
| stl.h:396:3:396:3 | pair | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
|
| stl.h:396:3:396:3 | pair | (const deque &,const Allocator &) | deque<T,Allocator> | deque | 1 |
|
||||||
@@ -215,6 +220,19 @@ signatureMatches
|
|||||||
| stl.h:396:3:396:3 | pair | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 |
|
| stl.h:396:3:396:3 | pair | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 |
|
||||||
| stl.h:396:3:396:3 | pair | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 |
|
| stl.h:396:3:396:3 | pair | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 |
|
||||||
| stl.h:396:3:396:3 | pair | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 |
|
| stl.h:396:3:396:3 | pair | (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 |
|
||||||
|
| stl.h:440:36:440:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:440:36:440:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:448:48:448:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:448:48:448:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:452:42:452:57 | insert_or_assign | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:508:36:508:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:508:36:508:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:520:42:520:57 | insert_or_assign | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | deque | assign<InputIt> | 0 |
|
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | deque | assign<InputIt> | 0 |
|
||||||
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | deque | assign<InputIt> | 1 |
|
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | deque | assign<InputIt> | 1 |
|
||||||
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | forward_list | assign<InputIt> | 0 |
|
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | forward_list | assign<InputIt> | 0 |
|
||||||
@@ -223,6 +241,8 @@ signatureMatches
|
|||||||
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | list | assign<InputIt> | 1 |
|
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | list | assign<InputIt> | 1 |
|
||||||
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | vector | assign<InputIt> | 0 |
|
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | vector | assign<InputIt> | 0 |
|
||||||
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | vector | assign<InputIt> | 1 |
|
| stl.h:557:33:557:35 | set | (InputIt,InputIt) | vector | assign<InputIt> | 1 |
|
||||||
|
| stl.h:569:36:569:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:569:36:569:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 0 |
|
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 0 |
|
||||||
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 1 |
|
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 1 |
|
||||||
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | forward_list | assign<InputIt> | 0 |
|
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | forward_list | assign<InputIt> | 0 |
|
||||||
@@ -231,6 +251,8 @@ signatureMatches
|
|||||||
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | list | assign<InputIt> | 1 |
|
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | list | assign<InputIt> | 1 |
|
||||||
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 0 |
|
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 0 |
|
||||||
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 1 |
|
| stl.h:574:38:574:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 1 |
|
||||||
|
| stl.h:623:36:623:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:623:36:623:47 | emplace_hint | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 0 |
|
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 0 |
|
||||||
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 1 |
|
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | deque | assign<InputIt> | 1 |
|
||||||
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | forward_list | assign<InputIt> | 0 |
|
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | forward_list | assign<InputIt> | 0 |
|
||||||
@@ -239,6 +261,10 @@ signatureMatches
|
|||||||
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | list | assign<InputIt> | 1 |
|
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | list | assign<InputIt> | 1 |
|
||||||
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 0 |
|
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 0 |
|
||||||
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 1 |
|
| stl.h:628:38:628:43 | insert | (InputIt,InputIt) | vector | assign<InputIt> | 1 |
|
||||||
|
| stl.h:678:33:678:38 | format | (format_string,Args &&) | | format<Args> | 0 |
|
||||||
|
| stl.h:678:33:678:38 | format | (format_string,Args &&) | | format<Args> | 0 |
|
||||||
|
| stl.h:678:33:678:38 | format | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
|
| stl.h:678:33:678:38 | format | (format_string,Args &&) | | format<Args> | 1 |
|
||||||
getSignatureParameterName
|
getSignatureParameterName
|
||||||
| (InputIt,InputIt) | deque | assign<InputIt> | 0 | func:0 |
|
| (InputIt,InputIt) | deque | assign<InputIt> | 0 | func:0 |
|
||||||
| (InputIt,InputIt) | deque | assign<InputIt> | 1 | func:0 |
|
| (InputIt,InputIt) | deque | assign<InputIt> | 1 | func:0 |
|
||||||
@@ -315,6 +341,8 @@ getSignatureParameterName
|
|||||||
| (deque &&) | deque | deque | 0 | deque && |
|
| (deque &&) | deque | deque | 0 | deque && |
|
||||||
| (deque &&,const Allocator &) | deque<T,Allocator> | deque | 0 | deque && |
|
| (deque &&,const Allocator &) | deque<T,Allocator> | deque | 0 | deque && |
|
||||||
| (deque &&,const Allocator &) | deque<T,Allocator> | deque | 1 | const class:1 & |
|
| (deque &&,const Allocator &) | deque<T,Allocator> | deque | 1 | const class:1 & |
|
||||||
|
| (format_string,Args &&) | | format<Args> | 0 | format_string |
|
||||||
|
| (format_string,Args &&) | | format<Args> | 1 | func:0 && |
|
||||||
| (forward_list &&) | forward_list | forward_list | 0 | forward_list && |
|
| (forward_list &&) | forward_list | forward_list | 0 | forward_list && |
|
||||||
| (forward_list &&,const Allocator &) | forward_list<T,Allocator> | forward_list | 0 | forward_list && |
|
| (forward_list &&,const Allocator &) | forward_list<T,Allocator> | forward_list | 0 | forward_list && |
|
||||||
| (forward_list &&,const Allocator &) | forward_list<T,Allocator> | forward_list | 1 | const class:1 & |
|
| (forward_list &&,const Allocator &) | forward_list<T,Allocator> | forward_list | 1 | const class:1 & |
|
||||||
@@ -345,6 +373,14 @@ getSignatureParameterName
|
|||||||
| (vector &&,const Allocator &) | vector<T,Allocator> | vector | 0 | vector && |
|
| (vector &&,const Allocator &) | vector<T,Allocator> | vector | 0 | vector && |
|
||||||
| (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 | const class:1 & |
|
| (vector &&,const Allocator &) | vector<T,Allocator> | vector | 1 | const class:1 & |
|
||||||
getParameterTypeName
|
getParameterTypeName
|
||||||
|
| smart_pointer.cpp:7:27:7:30 | sink | 0 | shared_ptr & |
|
||||||
|
| smart_pointer.cpp:7:27:7:30 | sink | 0 | shared_ptr & |
|
||||||
|
| smart_pointer.cpp:8:27:8:30 | sink | 0 | unique_ptr & |
|
||||||
|
| smart_pointer.cpp:8:27:8:30 | sink | 0 | unique_ptr & |
|
||||||
|
| stl.h:29:34:29:40 | forward | 0 | remove_reference_t & |
|
||||||
|
| stl.h:29:34:29:40 | forward | 0 | remove_reference_t & |
|
||||||
|
| stl.h:29:34:29:40 | forward | 0 | remove_reference_t & |
|
||||||
|
| stl.h:29:34:29:40 | forward | 0 | remove_reference_t & |
|
||||||
| stl.h:49:3:49:10 | iterator | 0 | const iterator & |
|
| stl.h:49:3:49:10 | iterator | 0 | const iterator & |
|
||||||
| stl.h:49:3:49:10 | iterator | 0 | const iterator & |
|
| stl.h:49:3:49:10 | iterator | 0 | const iterator & |
|
||||||
| stl.h:49:3:49:10 | iterator | 0 | const iterator & |
|
| stl.h:49:3:49:10 | iterator | 0 | const iterator & |
|
||||||
@@ -377,6 +413,8 @@ getParameterTypeName
|
|||||||
| stl.h:88:25:88:33 | operator= | 0 | value_type && |
|
| stl.h:88:25:88:33 | operator= | 0 | value_type && |
|
||||||
| stl.h:91:24:91:33 | operator++ | 0 | int |
|
| stl.h:91:24:91:33 | operator++ | 0 | int |
|
||||||
| stl.h:91:24:91:33 | operator++ | 0 | int |
|
| stl.h:91:24:91:33 | operator++ | 0 | int |
|
||||||
|
| stl.h:95:44:95:44 | back_inserter | 0 | func:0 & |
|
||||||
|
| stl.h:95:44:95:44 | back_inserter | 0 | func:0 & |
|
||||||
| stl.h:148:3:148:14 | basic_string | 0 | const class:2 & |
|
| stl.h:148:3:148:14 | basic_string | 0 | const class:2 & |
|
||||||
| stl.h:149:33:149:44 | basic_string | 0 | const class:0 * |
|
| stl.h:149:33:149:44 | basic_string | 0 | const class:0 * |
|
||||||
| stl.h:149:33:149:44 | basic_string | 1 | const class:2 & |
|
| stl.h:149:33:149:44 | basic_string | 1 | const class:2 & |
|
||||||
@@ -425,6 +463,10 @@ getParameterTypeName
|
|||||||
| stl.h:193:8:193:12 | clear | 2 | size_type |
|
| stl.h:193:8:193:12 | clear | 2 | size_type |
|
||||||
| stl.h:195:8:195:11 | swap | 0 | size_type |
|
| stl.h:195:8:195:11 | swap | 0 | size_type |
|
||||||
| stl.h:195:8:195:11 | swap | 1 | size_type |
|
| stl.h:195:8:195:11 | swap | 1 | size_type |
|
||||||
|
| stl.h:198:94:198:102 | operator+ | 0 | const basic_string & |
|
||||||
|
| stl.h:198:94:198:102 | operator+ | 1 | const basic_string & |
|
||||||
|
| stl.h:199:94:199:102 | operator+ | 0 | const basic_string & |
|
||||||
|
| stl.h:199:94:199:102 | operator+ | 1 | const func:0 * |
|
||||||
| stl.h:214:33:214:42 | operator>> | 0 | int & |
|
| stl.h:214:33:214:42 | operator>> | 0 | int & |
|
||||||
| stl.h:217:33:217:35 | get | 0 | char_type & |
|
| stl.h:217:33:217:35 | get | 0 | char_type & |
|
||||||
| stl.h:218:33:218:35 | get | 0 | char_type * |
|
| stl.h:218:33:218:35 | get | 0 | char_type * |
|
||||||
@@ -439,10 +481,23 @@ getParameterTypeName
|
|||||||
| stl.h:226:32:226:38 | getline | 0 | char_type * |
|
| stl.h:226:32:226:38 | getline | 0 | char_type * |
|
||||||
| stl.h:226:32:226:38 | getline | 1 | streamsize |
|
| stl.h:226:32:226:38 | getline | 1 | streamsize |
|
||||||
| stl.h:226:32:226:38 | getline | 2 | char_type |
|
| stl.h:226:32:226:38 | getline | 2 | char_type |
|
||||||
|
| stl.h:229:68:229:77 | operator>> | 0 | basic_istream & |
|
||||||
|
| stl.h:229:68:229:77 | operator>> | 1 | func:0 * |
|
||||||
|
| stl.h:230:85:230:94 | operator>> | 0 | basic_istream & |
|
||||||
|
| stl.h:230:85:230:94 | operator>> | 1 | basic_string & |
|
||||||
|
| stl.h:232:84:232:90 | getline | 0 | basic_istream & |
|
||||||
|
| stl.h:232:84:232:90 | getline | 1 | basic_string & |
|
||||||
|
| stl.h:232:84:232:90 | getline | 2 | func:0 |
|
||||||
|
| stl.h:233:84:233:90 | getline | 0 | basic_istream & |
|
||||||
|
| stl.h:233:84:233:90 | getline | 1 | basic_string & |
|
||||||
| stl.h:240:33:240:42 | operator<< | 0 | int |
|
| stl.h:240:33:240:42 | operator<< | 0 | int |
|
||||||
| stl.h:242:33:242:35 | put | 0 | char_type |
|
| stl.h:242:33:242:35 | put | 0 | char_type |
|
||||||
| stl.h:243:33:243:37 | write | 0 | const char_type * |
|
| stl.h:243:33:243:37 | write | 0 | const char_type * |
|
||||||
| stl.h:243:33:243:37 | write | 1 | streamsize |
|
| stl.h:243:33:243:37 | write | 1 | streamsize |
|
||||||
|
| stl.h:247:67:247:76 | operator<< | 0 | basic_ostream & |
|
||||||
|
| stl.h:247:67:247:76 | operator<< | 1 | const func:0 * |
|
||||||
|
| stl.h:248:85:248:94 | operator<< | 0 | basic_ostream & |
|
||||||
|
| stl.h:248:85:248:94 | operator<< | 1 | const basic_string & |
|
||||||
| stl.h:259:12:259:29 | basic_stringstream | 0 | const basic_string & |
|
| stl.h:259:12:259:29 | basic_stringstream | 0 | const basic_string & |
|
||||||
| stl.h:263:23:263:31 | operator= | 0 | basic_stringstream && |
|
| stl.h:263:23:263:31 | operator= | 0 | basic_stringstream && |
|
||||||
| stl.h:265:8:265:11 | swap | 0 | basic_stringstream & |
|
| stl.h:265:8:265:11 | swap | 0 | basic_stringstream & |
|
||||||
@@ -496,11 +551,20 @@ getParameterTypeName
|
|||||||
| stl.h:333:42:333:47 | insert | 1 | func:0 |
|
| stl.h:333:42:333:47 | insert | 1 | func:0 |
|
||||||
| stl.h:333:42:333:47 | insert | 2 | func:0 |
|
| stl.h:333:42:333:47 | insert | 2 | func:0 |
|
||||||
| stl.h:333:42:333:47 | insert | 2 | func:0 |
|
| stl.h:333:42:333:47 | insert | 2 | func:0 |
|
||||||
|
| stl.h:335:37:335:43 | emplace | 0 | const_iterator |
|
||||||
|
| stl.h:335:37:335:43 | emplace | 1 | func:0 && |
|
||||||
|
| stl.h:336:33:336:44 | emplace_back | 0 | func:0 && |
|
||||||
| stl.h:338:8:338:11 | swap | 0 | vector & |
|
| stl.h:338:8:338:11 | swap | 0 | vector & |
|
||||||
| stl.h:351:12:351:21 | shared_ptr | 0 | class:0 * |
|
| stl.h:351:12:351:21 | shared_ptr | 0 | class:0 * |
|
||||||
| stl.h:352:3:352:12 | shared_ptr | 0 | const shared_ptr & |
|
| stl.h:352:3:352:12 | shared_ptr | 0 | const shared_ptr & |
|
||||||
| stl.h:352:3:352:12 | shared_ptr | 0 | const shared_ptr & |
|
| stl.h:352:3:352:12 | shared_ptr | 0 | const shared_ptr & |
|
||||||
| stl.h:369:12:369:21 | unique_ptr | 0 | class:0 * |
|
| stl.h:369:12:369:21 | unique_ptr | 0 | class:0 * |
|
||||||
|
| stl.h:380:52:380:62 | make_unique | 0 | func:1 && |
|
||||||
|
| stl.h:380:52:380:62 | make_unique | 0 | func:1 && |
|
||||||
|
| stl.h:380:52:380:62 | make_unique | 0 | func:1 && |
|
||||||
|
| stl.h:382:52:382:62 | make_shared | 0 | func:1 && |
|
||||||
|
| stl.h:382:52:382:62 | make_shared | 0 | func:1 && |
|
||||||
|
| stl.h:382:52:382:62 | make_shared | 0 | func:1 && |
|
||||||
| stl.h:396:3:396:3 | pair | 0 | const class:0 & |
|
| stl.h:396:3:396:3 | pair | 0 | const class:0 & |
|
||||||
| stl.h:396:3:396:3 | pair | 0 | const class:0 & |
|
| stl.h:396:3:396:3 | pair | 0 | const class:0 & |
|
||||||
| stl.h:396:3:396:3 | pair | 0 | const class:0 & |
|
| stl.h:396:3:396:3 | pair | 0 | const class:0 & |
|
||||||
@@ -524,14 +588,42 @@ getParameterTypeName
|
|||||||
| stl.h:397:30:397:33 | pair | 0 | const pair & |
|
| stl.h:397:30:397:33 | pair | 0 | const pair & |
|
||||||
| stl.h:397:30:397:33 | pair | 0 | const pair & |
|
| stl.h:397:30:397:33 | pair | 0 | const pair & |
|
||||||
| stl.h:399:8:399:11 | swap | 0 | pair & |
|
| stl.h:399:8:399:11 | swap | 0 | pair & |
|
||||||
|
| stl.h:402:72:402:72 | make_pair | 0 | func:0 && |
|
||||||
|
| stl.h:402:72:402:72 | make_pair | 0 | func:0 && |
|
||||||
|
| stl.h:402:72:402:72 | make_pair | 0 | func:0 && |
|
||||||
|
| stl.h:402:72:402:72 | make_pair | 0 | func:0 && |
|
||||||
|
| stl.h:402:72:402:72 | make_pair | 0 | func:0 && |
|
||||||
|
| stl.h:402:72:402:72 | make_pair | 0 | func:0 && |
|
||||||
|
| stl.h:402:72:402:72 | make_pair | 1 | func:1 && |
|
||||||
|
| stl.h:402:72:402:72 | make_pair | 1 | func:1 && |
|
||||||
|
| stl.h:402:72:402:72 | make_pair | 1 | func:1 && |
|
||||||
|
| stl.h:402:72:402:72 | make_pair | 1 | func:1 && |
|
||||||
|
| stl.h:402:72:402:72 | make_pair | 1 | func:1 && |
|
||||||
|
| stl.h:402:72:402:72 | make_pair | 1 | func:1 && |
|
||||||
| stl.h:422:3:422:5 | map | 0 | const map & |
|
| stl.h:422:3:422:5 | map | 0 | const map & |
|
||||||
| stl.h:426:8:426:16 | operator= | 0 | const map & |
|
| stl.h:426:8:426:16 | operator= | 0 | const map & |
|
||||||
| stl.h:435:6:435:15 | operator[] | 0 | key_type && |
|
| stl.h:435:6:435:15 | operator[] | 0 | key_type && |
|
||||||
| stl.h:435:6:435:15 | operator[] | 0 | key_type && |
|
| stl.h:435:6:435:15 | operator[] | 0 | key_type && |
|
||||||
| stl.h:436:6:436:7 | at | 0 | const key_type & |
|
| stl.h:436:6:436:7 | at | 0 | const key_type & |
|
||||||
|
| stl.h:439:48:439:54 | emplace | 0 | func:0 && |
|
||||||
|
| stl.h:439:48:439:54 | emplace | 0 | func:0 && |
|
||||||
|
| stl.h:440:36:440:47 | emplace_hint | 0 | const_iterator |
|
||||||
|
| stl.h:440:36:440:47 | emplace_hint | 0 | const_iterator |
|
||||||
|
| stl.h:440:36:440:47 | emplace_hint | 1 | func:0 && |
|
||||||
|
| stl.h:440:36:440:47 | emplace_hint | 1 | func:0 && |
|
||||||
| stl.h:443:24:443:29 | insert | 0 | value_type && |
|
| stl.h:443:24:443:29 | insert | 0 | value_type && |
|
||||||
| stl.h:445:12:445:17 | insert | 0 | const_iterator |
|
| stl.h:445:12:445:17 | insert | 0 | const_iterator |
|
||||||
| stl.h:445:12:445:17 | insert | 1 | value_type && |
|
| stl.h:445:12:445:17 | insert | 1 | value_type && |
|
||||||
|
| stl.h:448:48:448:58 | try_emplace | 0 | key_type && |
|
||||||
|
| stl.h:448:48:448:58 | try_emplace | 0 | key_type && |
|
||||||
|
| stl.h:448:48:448:58 | try_emplace | 1 | func:0 && |
|
||||||
|
| stl.h:448:48:448:58 | try_emplace | 1 | func:0 && |
|
||||||
|
| stl.h:450:36:450:46 | try_emplace | 0 | const_iterator |
|
||||||
|
| stl.h:450:36:450:46 | try_emplace | 0 | const_iterator |
|
||||||
|
| stl.h:450:36:450:46 | try_emplace | 1 | key_type && |
|
||||||
|
| stl.h:450:36:450:46 | try_emplace | 1 | key_type && |
|
||||||
|
| stl.h:450:36:450:46 | try_emplace | 2 | func:0 && |
|
||||||
|
| stl.h:450:36:450:46 | try_emplace | 2 | func:0 && |
|
||||||
| stl.h:452:42:452:57 | insert_or_assign | 0 | key_type && |
|
| stl.h:452:42:452:57 | insert_or_assign | 0 | key_type && |
|
||||||
| stl.h:452:42:452:57 | insert_or_assign | 1 | func:0 && |
|
| stl.h:452:42:452:57 | insert_or_assign | 1 | func:0 && |
|
||||||
| stl.h:454:30:454:45 | insert_or_assign | 0 | const_iterator |
|
| stl.h:454:30:454:45 | insert_or_assign | 0 | const_iterator |
|
||||||
@@ -550,9 +642,34 @@ getParameterTypeName
|
|||||||
| stl.h:503:16:503:25 | operator[] | 0 | key_type && |
|
| stl.h:503:16:503:25 | operator[] | 0 | key_type && |
|
||||||
| stl.h:503:16:503:25 | operator[] | 0 | key_type && |
|
| stl.h:503:16:503:25 | operator[] | 0 | key_type && |
|
||||||
| stl.h:504:16:504:17 | at | 0 | const key_type & |
|
| stl.h:504:16:504:17 | at | 0 | const key_type & |
|
||||||
|
| stl.h:507:48:507:54 | emplace | 0 | func:0 && |
|
||||||
|
| stl.h:507:48:507:54 | emplace | 0 | func:0 && |
|
||||||
|
| stl.h:507:48:507:54 | emplace | 0 | func:0 && |
|
||||||
|
| stl.h:507:48:507:54 | emplace | 0 | func:0 && |
|
||||||
|
| stl.h:507:48:507:54 | emplace | 0 | func:0 && |
|
||||||
|
| stl.h:508:36:508:47 | emplace_hint | 0 | const_iterator |
|
||||||
|
| stl.h:508:36:508:47 | emplace_hint | 0 | const_iterator |
|
||||||
|
| stl.h:508:36:508:47 | emplace_hint | 1 | func:0 && |
|
||||||
|
| stl.h:508:36:508:47 | emplace_hint | 1 | func:0 && |
|
||||||
| stl.h:511:24:511:29 | insert | 0 | value_type && |
|
| stl.h:511:24:511:29 | insert | 0 | value_type && |
|
||||||
| stl.h:513:12:513:17 | insert | 0 | const_iterator |
|
| stl.h:513:12:513:17 | insert | 0 | const_iterator |
|
||||||
| stl.h:513:12:513:17 | insert | 1 | value_type && |
|
| stl.h:513:12:513:17 | insert | 1 | value_type && |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | 0 | key_type && |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | 0 | key_type && |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | 0 | key_type && |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | 0 | key_type && |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | 0 | key_type && |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | 1 | func:0 && |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | 1 | func:0 && |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | 1 | func:0 && |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | 1 | func:0 && |
|
||||||
|
| stl.h:516:48:516:58 | try_emplace | 1 | func:0 && |
|
||||||
|
| stl.h:518:36:518:46 | try_emplace | 0 | const_iterator |
|
||||||
|
| stl.h:518:36:518:46 | try_emplace | 0 | const_iterator |
|
||||||
|
| stl.h:518:36:518:46 | try_emplace | 1 | key_type && |
|
||||||
|
| stl.h:518:36:518:46 | try_emplace | 1 | key_type && |
|
||||||
|
| stl.h:518:36:518:46 | try_emplace | 2 | func:0 && |
|
||||||
|
| stl.h:518:36:518:46 | try_emplace | 2 | func:0 && |
|
||||||
| stl.h:520:42:520:57 | insert_or_assign | 0 | key_type && |
|
| stl.h:520:42:520:57 | insert_or_assign | 0 | key_type && |
|
||||||
| stl.h:520:42:520:57 | insert_or_assign | 1 | func:0 && |
|
| stl.h:520:42:520:57 | insert_or_assign | 1 | func:0 && |
|
||||||
| stl.h:522:30:522:45 | insert_or_assign | 0 | const_iterator |
|
| stl.h:522:30:522:45 | insert_or_assign | 0 | const_iterator |
|
||||||
@@ -567,6 +684,12 @@ getParameterTypeName
|
|||||||
| stl.h:557:33:557:35 | set | 0 | func:0 |
|
| stl.h:557:33:557:35 | set | 0 | func:0 |
|
||||||
| stl.h:557:33:557:35 | set | 1 | func:0 |
|
| stl.h:557:33:557:35 | set | 1 | func:0 |
|
||||||
| stl.h:560:8:560:16 | operator= | 0 | const set & |
|
| stl.h:560:8:560:16 | operator= | 0 | const set & |
|
||||||
|
| stl.h:568:48:568:54 | emplace | 0 | func:0 && |
|
||||||
|
| stl.h:568:48:568:54 | emplace | 0 | func:0 && |
|
||||||
|
| stl.h:569:36:569:47 | emplace_hint | 0 | const_iterator |
|
||||||
|
| stl.h:569:36:569:47 | emplace_hint | 0 | const_iterator |
|
||||||
|
| stl.h:569:36:569:47 | emplace_hint | 1 | func:0 && |
|
||||||
|
| stl.h:569:36:569:47 | emplace_hint | 1 | func:0 && |
|
||||||
| stl.h:571:23:571:28 | insert | 0 | value_type && |
|
| stl.h:571:23:571:28 | insert | 0 | value_type && |
|
||||||
| stl.h:573:12:573:17 | insert | 0 | const_iterator |
|
| stl.h:573:12:573:17 | insert | 0 | const_iterator |
|
||||||
| stl.h:573:12:573:17 | insert | 1 | value_type && |
|
| stl.h:573:12:573:17 | insert | 1 | value_type && |
|
||||||
@@ -584,6 +707,12 @@ getParameterTypeName
|
|||||||
| stl.h:611:33:611:45 | unordered_set | 1 | func:0 |
|
| stl.h:611:33:611:45 | unordered_set | 1 | func:0 |
|
||||||
| stl.h:611:33:611:45 | unordered_set | 2 | size_type |
|
| stl.h:611:33:611:45 | unordered_set | 2 | size_type |
|
||||||
| stl.h:614:18:614:26 | operator= | 0 | const unordered_set & |
|
| stl.h:614:18:614:26 | operator= | 0 | const unordered_set & |
|
||||||
|
| stl.h:622:48:622:54 | emplace | 0 | func:0 && |
|
||||||
|
| stl.h:622:48:622:54 | emplace | 0 | func:0 && |
|
||||||
|
| stl.h:623:36:623:47 | emplace_hint | 0 | const_iterator |
|
||||||
|
| stl.h:623:36:623:47 | emplace_hint | 0 | const_iterator |
|
||||||
|
| stl.h:623:36:623:47 | emplace_hint | 1 | func:0 && |
|
||||||
|
| stl.h:623:36:623:47 | emplace_hint | 1 | func:0 && |
|
||||||
| stl.h:625:24:625:29 | insert | 0 | value_type && |
|
| stl.h:625:24:625:29 | insert | 0 | value_type && |
|
||||||
| stl.h:627:12:627:17 | insert | 0 | const_iterator |
|
| stl.h:627:12:627:17 | insert | 0 | const_iterator |
|
||||||
| stl.h:627:12:627:17 | insert | 1 | value_type && |
|
| stl.h:627:12:627:17 | insert | 1 | value_type && |
|
||||||
@@ -594,3 +723,18 @@ getParameterTypeName
|
|||||||
| stl.h:636:37:636:41 | merge | 0 | unordered_set & |
|
| stl.h:636:37:636:41 | merge | 0 | unordered_set & |
|
||||||
| stl.h:639:12:639:15 | find | 0 | const key_type & |
|
| stl.h:639:12:639:15 | find | 0 | const key_type & |
|
||||||
| stl.h:641:28:641:38 | equal_range | 0 | const key_type & |
|
| stl.h:641:28:641:38 | equal_range | 0 | const key_type & |
|
||||||
|
| stl.h:671:21:671:39 | basic_format_string | 0 | const func:0 & |
|
||||||
|
| stl.h:671:21:671:39 | basic_format_string | 0 | const func:0 & |
|
||||||
|
| stl.h:678:33:678:38 | format | 0 | format_string |
|
||||||
|
| stl.h:678:33:678:38 | format | 0 | format_string |
|
||||||
|
| stl.h:678:33:678:38 | format | 1 | func:0 && |
|
||||||
|
| stl.h:678:33:678:38 | format | 1 | func:0 && |
|
||||||
|
| stringstream.cpp:18:6:18:9 | sink | 0 | const basic_ostream> & |
|
||||||
|
| stringstream.cpp:21:6:21:9 | sink | 0 | const basic_istream> & |
|
||||||
|
| stringstream.cpp:24:6:24:9 | sink | 0 | const basic_iostream> & |
|
||||||
|
| swap1.cpp:14:9:14:9 | move | 0 | func:0 & |
|
||||||
|
| swap2.cpp:14:9:14:9 | move | 0 | func:0 & |
|
||||||
|
| swap.h:4:20:4:23 | swap | 0 | func:0 & |
|
||||||
|
| swap.h:4:20:4:23 | swap | 1 | func:0 & |
|
||||||
|
| vector.cpp:14:27:14:30 | sink | 0 | vector> & |
|
||||||
|
| vector.cpp:14:27:14:30 | sink | 0 | vector> & |
|
||||||
|
|||||||
@@ -62,3 +62,9 @@ Virtual getAVirtual();
|
|||||||
void test9() {
|
void test9() {
|
||||||
typeid(getAVirtual()); // unevaluated
|
typeid(getAVirtual()); // unevaluated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void constExprIf() {
|
||||||
|
if constexpr(sizeof(int) == 4) { } // unevaluated
|
||||||
|
}
|
||||||
|
|
||||||
|
// semmle-extractor-options: -std=c++20
|
||||||
@@ -14,3 +14,7 @@
|
|||||||
| test.cpp:57:9:57:9 | 4 |
|
| test.cpp:57:9:57:9 | 4 |
|
||||||
| test.cpp:63:9:63:19 | call to getAVirtual |
|
| test.cpp:63:9:63:19 | call to getAVirtual |
|
||||||
| test.cpp:63:9:63:21 | temporary object |
|
| test.cpp:63:9:63:21 | temporary object |
|
||||||
|
| test.cpp:67:16:67:26 | sizeof(int) |
|
||||||
|
| test.cpp:67:16:67:31 | ... == ... |
|
||||||
|
| test.cpp:67:31:67:31 | 4 |
|
||||||
|
| test.cpp:67:31:67:31 | (unsigned long)... |
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,6 @@ missingOperand
|
|||||||
unexpectedOperand
|
unexpectedOperand
|
||||||
duplicateOperand
|
duplicateOperand
|
||||||
missingPhiOperand
|
missingPhiOperand
|
||||||
| 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) |
|
|
||||||
missingOperandType
|
missingOperandType
|
||||||
duplicateChiOperand
|
duplicateChiOperand
|
||||||
sideEffectWithoutPrimary
|
sideEffectWithoutPrimary
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ missingOperand
|
|||||||
unexpectedOperand
|
unexpectedOperand
|
||||||
duplicateOperand
|
duplicateOperand
|
||||||
missingPhiOperand
|
missingPhiOperand
|
||||||
| 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) |
|
|
||||||
missingOperandType
|
missingOperandType
|
||||||
duplicateChiOperand
|
duplicateChiOperand
|
||||||
sideEffectWithoutPrimary
|
sideEffectWithoutPrimary
|
||||||
|
|||||||
3095
cpp/ql/test/library-tests/ir/ir/many-defs-per-use.cpp
Normal file
3095
cpp/ql/test/library-tests/ir/ir/many-defs-per-use.cpp
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -7,4 +7,61 @@ class TestConstexpr {
|
|||||||
constexpr int member_const_constexpr() const { return 0; }
|
constexpr int member_const_constexpr() const { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TestExplict {
|
||||||
|
explicit TestExplict();
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct TestExplicitBool {
|
||||||
|
explicit(sizeof(T) == 1)
|
||||||
|
TestExplicitBool(const T);
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit TestExplicitBool(const double) -> TestExplicitBool<int>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
explicit(sizeof(T) == 4)
|
||||||
|
TestExplicitBool(const T) -> TestExplicitBool<int>;
|
||||||
|
|
||||||
|
void TestExplicitBoolFun() {
|
||||||
|
new TestExplicitBool<char>(0);
|
||||||
|
new TestExplicitBool<int>(0);
|
||||||
|
new TestExplicitBool(0.0f);
|
||||||
|
new TestExplicitBool(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct TestExplicitBool2 {
|
||||||
|
explicit(sizeof(T) == 1)
|
||||||
|
TestExplicitBool2(const T);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
TestExplicitBool2<T>::TestExplicitBool2(const T) { }
|
||||||
|
|
||||||
|
void TestExplicitBoolFun2() {
|
||||||
|
new TestExplicitBool2<char>(0);
|
||||||
|
new TestExplicitBool2<int>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct TestExplicitBool3 {
|
||||||
|
template<typename U>
|
||||||
|
explicit(sizeof(T) == 1)
|
||||||
|
TestExplicitBool3(const T, const U);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> template<typename U>
|
||||||
|
TestExplicitBool3<T>::TestExplicitBool3(const T, const U) { }
|
||||||
|
|
||||||
|
void TestExplicitBoolFun3() {
|
||||||
|
new TestExplicitBool3<char>(0, 0);
|
||||||
|
new TestExplicitBool3<int>(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestExplicitBool4 {
|
||||||
|
explicit(sizeof(char) == 1)
|
||||||
|
TestExplicitBool4(const char);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace cpp20
|
} // namespace cpp20
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
| cpp20.cpp:15:8:15:23 | TestExplicitBool<char> | file://:0:0:0:0 | char | cpp20.cpp:17:5:17:20 | TestExplicitBool | explicit, extern, public |
|
||||||
|
| cpp20.cpp:15:8:15:23 | TestExplicitBool<int> | file://:0:0:0:0 | int | cpp20.cpp:17:5:17:20 | TestExplicitBool | extern, public |
|
||||||
|
| cpp20.cpp:34:8:34:24 | TestExplicitBool2<char> | file://:0:0:0:0 | char | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | explicit, public |
|
||||||
|
| cpp20.cpp:34:8:34:24 | TestExplicitBool2<int> | file://:0:0:0:0 | int | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | public |
|
||||||
|
| cpp20.cpp:48:8:48:24 | TestExplicitBool3<char> | file://:0:0:0:0 | char | cpp20.cpp:51:5:51:5 | TestExplicitBool3 | explicit, public |
|
||||||
|
| cpp20.cpp:48:8:48:24 | TestExplicitBool3<char> | file://:0:0:0:0 | char | cpp20.cpp:51:5:51:21 | TestExplicitBool3 | explicit, extern, public |
|
||||||
|
| cpp20.cpp:48:8:48:24 | TestExplicitBool3<int> | file://:0:0:0:0 | int | cpp20.cpp:51:5:51:5 | TestExplicitBool3 | public |
|
||||||
|
| cpp20.cpp:48:8:48:24 | TestExplicitBool3<int> | file://:0:0:0:0 | int | cpp20.cpp:51:5:51:21 | TestExplicitBool3 | extern, public |
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import cpp
|
||||||
|
|
||||||
|
from MemberFunction m, ClassTemplateInstantiation c, string specifiers
|
||||||
|
where
|
||||||
|
c.getAMember() = m and
|
||||||
|
specifiers = concat(string s | s = m.getASpecifier().getName() | s, ", ")
|
||||||
|
select c, c.getATemplateArgument(), m, specifiers
|
||||||
@@ -1,146 +1,81 @@
|
|||||||
| Class | specifiers2pp.cpp:8:7:8:13 | MyClass | MyClass | abstract |
|
| Class | specifiers2pp.cpp:8:7:8:13 | MyClass | MyClass | abstract |
|
||||||
| Class | specifiers2pp.cpp:24:7:24:14 | MyClass2 | MyClass2 | abstract |
|
| Class | specifiers2pp.cpp:24:7:24:14 | MyClass2 | MyClass2 | abstract |
|
||||||
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | extern |
|
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | extern, inline, is_constexpr, public |
|
||||||
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | extern |
|
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | extern, inline, is_constexpr, public |
|
||||||
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | inline |
|
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | declared_constexpr, inline, is_constexpr, private |
|
||||||
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | inline |
|
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | const, declared_constexpr, inline, is_constexpr, private |
|
||||||
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | is_constexpr |
|
| Function | cpp20.cpp:10:8:10:8 | TestExplict | TestExplict | extern, inline, is_constexpr, public |
|
||||||
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | is_constexpr |
|
| Function | cpp20.cpp:10:8:10:8 | TestExplict | TestExplict | extern, inline, is_constexpr, public |
|
||||||
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | public |
|
| Function | cpp20.cpp:10:8:10:8 | operator= | operator= | extern, inline, is_constexpr, public |
|
||||||
| Function | cpp20.cpp:5:7:5:7 | operator= | operator= | public |
|
| Function | cpp20.cpp:10:8:10:8 | operator= | operator= | extern, inline, is_constexpr, public |
|
||||||
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | declared_constexpr |
|
| Function | cpp20.cpp:11:14:11:24 | TestExplict | TestExplict | explicit, extern, public |
|
||||||
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | inline |
|
| Function | cpp20.cpp:17:5:17:20 | TestExplicitBool | TestExplicitBool | explicit, extern, public |
|
||||||
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | is_constexpr |
|
| Function | cpp20.cpp:17:5:17:20 | TestExplicitBool | TestExplicitBool | extern, public |
|
||||||
| Function | cpp20.cpp:6:19:6:34 | member_constexpr | member_constexpr | private |
|
| Function | cpp20.cpp:17:5:17:20 | TestExplicitBool | TestExplicitBool | extern, public |
|
||||||
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | const |
|
| Function | cpp20.cpp:24:1:24:16 | TestExplicitBool | TestExplicitBool | has_trailing_return_type |
|
||||||
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | declared_constexpr |
|
| Function | cpp20.cpp:40:1:40:39 | TestExplicitBool2 | TestExplicitBool2 | public |
|
||||||
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | inline |
|
| Function | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | TestExplicitBool2 | explicit, public |
|
||||||
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | is_constexpr |
|
| Function | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | TestExplicitBool2 | public |
|
||||||
| Function | cpp20.cpp:7:19:7:40 | member_const_constexpr | member_const_constexpr | private |
|
| Function | cpp20.cpp:40:23:40:23 | TestExplicitBool2 | TestExplicitBool2 | public |
|
||||||
| Function | specifiers2.c:11:6:11:6 | f | f | c_linkage |
|
| Function | cpp20.cpp:51:5:51:5 | TestExplicitBool3 | TestExplicitBool3 | explicit, public |
|
||||||
| Function | specifiers2.c:11:6:11:6 | f | f | extern |
|
| Function | cpp20.cpp:51:5:51:5 | TestExplicitBool3 | TestExplicitBool3 | public |
|
||||||
| Function | specifiers2.c:12:13:12:13 | f | f | c_linkage |
|
| Function | cpp20.cpp:51:5:51:21 | TestExplicitBool3 | TestExplicitBool3 | explicit, extern, public |
|
||||||
| Function | specifiers2.c:12:13:12:13 | f | f | extern |
|
| Function | cpp20.cpp:51:5:51:21 | TestExplicitBool3 | TestExplicitBool3 | extern, public |
|
||||||
| Function | specifiers2.c:13:13:13:13 | f | f | c_linkage |
|
| Function | cpp20.cpp:55:1:55:39 | TestExplicitBool3 | TestExplicitBool3 | public |
|
||||||
| Function | specifiers2.c:13:13:13:13 | f | f | extern |
|
| Function | cpp20.cpp:62:8:62:8 | TestExplicitBool4 | TestExplicitBool4 | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2.c:15:13:15:13 | g | g | c_linkage |
|
| Function | cpp20.cpp:62:8:62:8 | TestExplicitBool4 | TestExplicitBool4 | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2.c:15:13:15:13 | g | g | extern |
|
| Function | cpp20.cpp:62:8:62:8 | operator= | operator= | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2.c:16:13:16:13 | g | g | c_linkage |
|
| Function | cpp20.cpp:62:8:62:8 | operator= | operator= | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2.c:16:13:16:13 | g | g | extern |
|
| Function | cpp20.cpp:64:5:64:21 | TestExplicitBool4 | TestExplicitBool4 | explicit, extern, public |
|
||||||
| Function | specifiers2.c:21:6:21:12 | somefun | somefun | c_linkage |
|
| Function | file://:0:0:0:0 | TestExplicitBool | TestExplicitBool | explicit, has_trailing_return_type |
|
||||||
| Function | specifiers2.c:21:6:21:12 | somefun | somefun | extern |
|
| Function | file://:0:0:0:0 | operator delete | operator delete | extern |
|
||||||
| Function | specifiers2.c:25:12:25:14 | add | add | c_linkage |
|
| Function | file://:0:0:0:0 | operator new | operator new | extern |
|
||||||
| Function | specifiers2.c:25:12:25:14 | add | add | inline |
|
| Function | specifiers2.c:11:6:11:6 | f | f | c_linkage, extern |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | extern |
|
| Function | specifiers2.c:12:13:12:13 | f | f | c_linkage, extern |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | extern |
|
| Function | specifiers2.c:13:13:13:13 | f | f | c_linkage, extern |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | inline |
|
| Function | specifiers2.c:15:13:15:13 | g | g | c_linkage, extern |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | inline |
|
| Function | specifiers2.c:16:13:16:13 | g | g | c_linkage, extern |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | is_constexpr |
|
| Function | specifiers2.c:21:6:21:12 | somefun | somefun | c_linkage, extern |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | is_constexpr |
|
| Function | specifiers2.c:25:12:25:14 | add | add | c_linkage, inline |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | public |
|
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | public |
|
| Function | specifiers2pp.cpp:8:7:8:7 | MyClass | MyClass | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | extern |
|
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | extern, inline, public |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | extern |
|
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | extern, inline, public |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | inline |
|
| Function | specifiers2pp.cpp:10:18:10:24 | MyClass | MyClass | explicit, extern, public |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | inline |
|
| Function | specifiers2pp.cpp:12:14:12:22 | publicFun | publicFun | inline, public |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | public |
|
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | declared_virtual, extern, public, pure, virtual |
|
||||||
| Function | specifiers2pp.cpp:8:7:8:7 | operator= | operator= | public |
|
| Function | specifiers2pp.cpp:14:21:14:21 | f | f | declared_virtual, extern, public, virtual |
|
||||||
| Function | specifiers2pp.cpp:10:18:10:24 | MyClass | MyClass | explicit |
|
| Function | specifiers2pp.cpp:18:14:18:23 | privateFun | privateFun | inline, private |
|
||||||
| Function | specifiers2pp.cpp:10:18:10:24 | MyClass | MyClass | extern |
|
| Function | specifiers2pp.cpp:21:14:21:25 | protectedFun | protectedFun | inline, protected |
|
||||||
| Function | specifiers2pp.cpp:10:18:10:24 | MyClass | MyClass | public |
|
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2pp.cpp:12:14:12:22 | publicFun | publicFun | inline |
|
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2pp.cpp:12:14:12:22 | publicFun | publicFun | public |
|
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern, inline, public |
|
||||||
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | declared_virtual |
|
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | extern, inline, public |
|
||||||
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | extern |
|
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | extern, inline, public |
|
||||||
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | public |
|
| Function | specifiers2pp.cpp:26:21:26:21 | f | f | declared_virtual, extern, override, public, virtual |
|
||||||
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | pure |
|
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2pp.cpp:13:21:13:26 | getInt | getInt | virtual |
|
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2pp.cpp:14:21:14:21 | f | f | declared_virtual |
|
|
||||||
| Function | specifiers2pp.cpp:14:21:14:21 | f | f | extern |
|
|
||||||
| Function | specifiers2pp.cpp:14:21:14:21 | f | f | public |
|
|
||||||
| Function | specifiers2pp.cpp:14:21:14:21 | f | f | virtual |
|
|
||||||
| Function | specifiers2pp.cpp:18:14:18:23 | privateFun | privateFun | inline |
|
|
||||||
| Function | specifiers2pp.cpp:18:14:18:23 | privateFun | privateFun | private |
|
|
||||||
| Function | specifiers2pp.cpp:21:14:21:25 | protectedFun | protectedFun | inline |
|
|
||||||
| Function | specifiers2pp.cpp:21:14:21:25 | protectedFun | protectedFun | protected |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | extern |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | inline |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | inline |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | inline |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | is_constexpr |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | is_constexpr |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | public |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | public |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | MyClass2 | MyClass2 | public |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | extern |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | extern |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | inline |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | inline |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | public |
|
|
||||||
| Function | specifiers2pp.cpp:24:7:24:7 | operator= | operator= | public |
|
|
||||||
| Function | specifiers2pp.cpp:26:21:26:21 | f | f | declared_virtual |
|
|
||||||
| Function | specifiers2pp.cpp:26:21:26:21 | f | f | extern |
|
|
||||||
| Function | specifiers2pp.cpp:26:21:26:21 | f | f | override |
|
|
||||||
| Function | specifiers2pp.cpp:26:21:26:21 | f | f | public |
|
|
||||||
| Function | specifiers2pp.cpp:26:21:26:21 | f | f | virtual |
|
|
||||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | extern |
|
|
||||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | extern |
|
|
||||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | inline |
|
|
||||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | inline |
|
|
||||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | is_constexpr |
|
|
||||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | is_constexpr |
|
|
||||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | public |
|
|
||||||
| Function | specifiers2pp.cpp:29:7:29:7 | operator= | operator= | public |
|
|
||||||
| Function | specifiers2pp.cpp:33:5:33:18 | fun | fun | public |
|
| Function | specifiers2pp.cpp:33:5:33:18 | fun | fun | public |
|
||||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | extern |
|
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | extern |
|
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | inline |
|
|
||||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | inline |
|
|
||||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | is_constexpr |
|
|
||||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | is_constexpr |
|
|
||||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | public |
|
|
||||||
| Function | specifiers2pp.cpp:35:7:35:7 | operator= | operator= | public |
|
|
||||||
| Function | specifiers2pp.cpp:40:12:40:18 | someFun | someFun | extern |
|
| Function | specifiers2pp.cpp:40:12:40:18 | someFun | someFun | extern |
|
||||||
| Function | specifiers2pp.cpp:41:16:41:23 | someFun2 | someFun2 | c_linkage |
|
| Function | specifiers2pp.cpp:41:16:41:23 | someFun2 | someFun2 | c_linkage, extern |
|
||||||
| Function | specifiers2pp.cpp:41:16:41:23 | someFun2 | someFun2 | extern |
|
| Function | specifiers2pp.cpp:43:9:43:16 | someFun3 | someFun3 | c_linkage, extern |
|
||||||
| Function | specifiers2pp.cpp:43:9:43:16 | someFun3 | someFun3 | c_linkage |
|
| Function | specifiers2pp.cpp:44:16:44:23 | someFun4 | someFun4 | c_linkage, static |
|
||||||
| Function | specifiers2pp.cpp:43:9:43:16 | someFun3 | someFun3 | extern |
|
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2pp.cpp:44:16:44:23 | someFun4 | someFun4 | c_linkage |
|
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | extern, inline, is_constexpr, public |
|
||||||
| Function | specifiers2pp.cpp:44:16:44:23 | someFun4 | someFun4 | static |
|
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | const, declared_constexpr, inline, is_constexpr, private |
|
||||||
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | extern |
|
| Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | const, declared_constexpr, inline, is_constexpr, private |
|
||||||
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | extern |
|
| FunctionDeclarationEntry | cpp20.cpp:11:14:11:24 | declaration of TestExplict | TestExplict | explicit |
|
||||||
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | inline |
|
| FunctionDeclarationEntry | cpp20.cpp:40:23:40:23 | definition of TestExplicitBool2 | TestExplicitBool2 | explicit |
|
||||||
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | inline |
|
| FunctionDeclarationEntry | cpp20.cpp:51:5:51:5 | definition of TestExplicitBool3 | TestExplicitBool3 | explicit |
|
||||||
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | is_constexpr |
|
| FunctionDeclarationEntry | cpp20.cpp:51:5:51:21 | declaration of TestExplicitBool3 | TestExplicitBool3 | explicit |
|
||||||
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | is_constexpr |
|
| FunctionDeclarationEntry | cpp20.cpp:64:5:64:21 | declaration of TestExplicitBool4 | TestExplicitBool4 | explicit |
|
||||||
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | public |
|
| FunctionDeclarationEntry | specifiers2.c:11:6:11:6 | declaration of f | f | c_linkage, void_param_list |
|
||||||
| Function | specifiers2pp.cpp:62:7:62:7 | operator= | operator= | public |
|
| FunctionDeclarationEntry | specifiers2.c:12:13:12:13 | declaration of f | f | c_linkage, extern, void_param_list |
|
||||||
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | const |
|
| FunctionDeclarationEntry | specifiers2.c:13:13:13:13 | declaration of f | f | c_linkage, extern, void_param_list |
|
||||||
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | declared_constexpr |
|
| FunctionDeclarationEntry | specifiers2.c:15:13:15:13 | declaration of g | g | c_linkage, extern, void_param_list |
|
||||||
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | inline |
|
| FunctionDeclarationEntry | specifiers2.c:16:13:16:13 | declaration of g | g | c_linkage, extern, void_param_list |
|
||||||
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | is_constexpr |
|
|
||||||
| Function | specifiers2pp.cpp:63:19:63:34 | member_constexpr | member_constexpr | private |
|
|
||||||
| Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | const |
|
|
||||||
| Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | declared_constexpr |
|
|
||||||
| Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | inline |
|
|
||||||
| Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | is_constexpr |
|
|
||||||
| Function | specifiers2pp.cpp:64:19:64:40 | member_const_constexpr | member_const_constexpr | private |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:11:6:11:6 | declaration of f | f | c_linkage |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:11:6:11:6 | declaration of f | f | void_param_list |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:12:13:12:13 | declaration of f | f | c_linkage |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:12:13:12:13 | declaration of f | f | extern |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:12:13:12:13 | declaration of f | f | void_param_list |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:13:13:13:13 | declaration of f | f | c_linkage |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:13:13:13:13 | declaration of f | f | extern |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:13:13:13:13 | declaration of f | f | void_param_list |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:15:13:15:13 | declaration of g | g | c_linkage |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:15:13:15:13 | declaration of g | g | extern |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:15:13:15:13 | declaration of g | g | void_param_list |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:16:13:16:13 | declaration of g | g | c_linkage |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:16:13:16:13 | declaration of g | g | extern |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:16:13:16:13 | declaration of g | g | void_param_list |
|
|
||||||
| FunctionDeclarationEntry | specifiers2.c:21:6:21:12 | declaration of somefun | somefun | c_linkage |
|
| FunctionDeclarationEntry | specifiers2.c:21:6:21:12 | declaration of somefun | somefun | c_linkage |
|
||||||
| FunctionDeclarationEntry | specifiers2.c:25:12:25:14 | definition of add | add | c_linkage |
|
| FunctionDeclarationEntry | specifiers2.c:25:12:25:14 | definition of add | add | c_linkage |
|
||||||
| FunctionDeclarationEntry | specifiers2pp.cpp:2:6:2:9 | definition of afun | afun | void_param_list |
|
| FunctionDeclarationEntry | specifiers2pp.cpp:2:6:2:9 | definition of afun | afun | void_param_list |
|
||||||
@@ -154,28 +89,19 @@
|
|||||||
| FunctionDeclarationEntry | specifiers2pp.cpp:31:13:31:15 | declaration of fun | fun | void_param_list |
|
| FunctionDeclarationEntry | specifiers2pp.cpp:31:13:31:15 | declaration of fun | fun | void_param_list |
|
||||||
| FunctionDeclarationEntry | specifiers2pp.cpp:33:5:33:18 | definition of fun | fun | void_param_list |
|
| FunctionDeclarationEntry | specifiers2pp.cpp:33:5:33:18 | definition of fun | fun | void_param_list |
|
||||||
| FunctionDeclarationEntry | specifiers2pp.cpp:40:12:40:18 | declaration of someFun | someFun | extern |
|
| FunctionDeclarationEntry | specifiers2pp.cpp:40:12:40:18 | declaration of someFun | someFun | extern |
|
||||||
| FunctionDeclarationEntry | specifiers2pp.cpp:41:16:41:23 | declaration of someFun2 | someFun2 | c_linkage |
|
| FunctionDeclarationEntry | specifiers2pp.cpp:41:16:41:23 | declaration of someFun2 | someFun2 | c_linkage, extern |
|
||||||
| FunctionDeclarationEntry | specifiers2pp.cpp:41:16:41:23 | declaration of someFun2 | someFun2 | extern |
|
| FunctionDeclarationEntry | specifiers2pp.cpp:43:9:43:16 | declaration of someFun3 | someFun3 | c_linkage, extern |
|
||||||
| FunctionDeclarationEntry | specifiers2pp.cpp:43:9:43:16 | declaration of someFun3 | someFun3 | c_linkage |
|
| FunctionDeclarationEntry | specifiers2pp.cpp:44:16:44:23 | declaration of someFun4 | someFun4 | c_linkage, static |
|
||||||
| FunctionDeclarationEntry | specifiers2pp.cpp:43:9:43:16 | declaration of someFun3 | someFun3 | extern |
|
|
||||||
| FunctionDeclarationEntry | specifiers2pp.cpp:44:16:44:23 | declaration of someFun4 | someFun4 | c_linkage |
|
|
||||||
| FunctionDeclarationEntry | specifiers2pp.cpp:44:16:44:23 | declaration of someFun4 | someFun4 | static |
|
|
||||||
| TypedefType | file://:0:0:0:0 | Const | Const | const |
|
| TypedefType | file://:0:0:0:0 | Const | Const | const |
|
||||||
| TypedefType | specifiers2.c:27:19:27:26 | constInt | constInt | const |
|
| TypedefType | specifiers2.c:27:19:27:26 | constInt | constInt | const |
|
||||||
| TypedefType | specifiers2pp.cpp:47:20:47:32 | const_pointer | const_pointer | const |
|
| TypedefType | specifiers2pp.cpp:47:20:47:32 | const_pointer | const_pointer | const |
|
||||||
| TypedefType | specifiers2pp.cpp:49:32:49:53 | volatile_const_pointer | volatile_const_pointer | const |
|
| TypedefType | specifiers2pp.cpp:49:32:49:53 | volatile_const_pointer | volatile_const_pointer | const, volatile |
|
||||||
| TypedefType | specifiers2pp.cpp:49:32:49:53 | volatile_const_pointer | volatile_const_pointer | volatile |
|
| TypedefType | specifiers2pp.cpp:50:32:50:54 | volatile_const_pointer2 | volatile_const_pointer2 | const, volatile |
|
||||||
| TypedefType | specifiers2pp.cpp:50:32:50:54 | volatile_const_pointer2 | volatile_const_pointer2 | const |
|
| TypedefType | specifiers2pp.cpp:53:23:53:45 | volatile_const_pointer3 | volatile_const_pointer3 | const, volatile |
|
||||||
| TypedefType | specifiers2pp.cpp:50:32:50:54 | volatile_const_pointer2 | volatile_const_pointer2 | volatile |
|
| TypedefType | specifiers2pp.cpp:54:44:54:74 | volatile_const_restrict_pointer | volatile_const_restrict_pointer | const, restrict, volatile |
|
||||||
| TypedefType | specifiers2pp.cpp:53:23:53:45 | volatile_const_pointer3 | volatile_const_pointer3 | const |
|
|
||||||
| TypedefType | specifiers2pp.cpp:53:23:53:45 | volatile_const_pointer3 | volatile_const_pointer3 | volatile |
|
|
||||||
| TypedefType | specifiers2pp.cpp:54:44:54:74 | volatile_const_restrict_pointer | volatile_const_restrict_pointer | const |
|
|
||||||
| TypedefType | specifiers2pp.cpp:54:44:54:74 | volatile_const_restrict_pointer | volatile_const_restrict_pointer | restrict |
|
|
||||||
| TypedefType | specifiers2pp.cpp:54:44:54:74 | volatile_const_restrict_pointer | volatile_const_restrict_pointer | volatile |
|
|
||||||
| TypedefType | specifiers2pp.cpp:56:28:56:32 | Const | Const | const |
|
| TypedefType | specifiers2pp.cpp:56:28:56:32 | Const | Const | const |
|
||||||
| TypedefType | specifiers2pp.cpp:58:7:58:15 | Const_int | Const_int | const |
|
| TypedefType | specifiers2pp.cpp:58:7:58:15 | Const_int | Const_int | const |
|
||||||
| TypedefType | specifiers2pp.cpp:60:28:60:45 | volatile_Const_int | volatile_Const_int | const |
|
| TypedefType | specifiers2pp.cpp:60:28:60:45 | volatile_Const_int | volatile_Const_int | const, volatile |
|
||||||
| TypedefType | specifiers2pp.cpp:60:28:60:45 | volatile_Const_int | volatile_Const_int | volatile |
|
|
||||||
| Variable | specifiers2.c:8:12:8:12 | j | j | extern |
|
| Variable | specifiers2.c:8:12:8:12 | j | j | extern |
|
||||||
| Variable | specifiers2.c:9:12:9:12 | j | j | extern |
|
| Variable | specifiers2.c:9:12:9:12 | j | j | extern |
|
||||||
| Variable | specifiers2.c:18:21:18:23 | svi | svi | static |
|
| Variable | specifiers2.c:18:21:18:23 | svi | svi | static |
|
||||||
|
|||||||
@@ -14,16 +14,20 @@ string interesting(Element e) {
|
|||||||
e instanceof VariableDeclarationEntry and result = "VariableDeclarationEntry"
|
e instanceof VariableDeclarationEntry and result = "VariableDeclarationEntry"
|
||||||
}
|
}
|
||||||
|
|
||||||
from Element e, string name, string specifier
|
from Element e, string name, string specifiers
|
||||||
where
|
where
|
||||||
(
|
(
|
||||||
name = e.(Declaration).getName() or
|
name = e.(Declaration).getName() or
|
||||||
name = e.(DeclarationEntry).getName() or
|
name = e.(DeclarationEntry).getName() or
|
||||||
name = e.(Type).toString()
|
name = e.(Type).toString()
|
||||||
) and
|
) and
|
||||||
(
|
specifiers =
|
||||||
specifier = e.(Declaration).getASpecifier().toString() or
|
concat(string s |
|
||||||
specifier = e.(DeclarationEntry).getASpecifier() or
|
s = e.(Declaration).getASpecifier().toString() or
|
||||||
specifier = e.(TypedefType).getBaseType().getASpecifier().toString()
|
s = e.(DeclarationEntry).getASpecifier() or
|
||||||
)
|
s = e.(TypedefType).getBaseType().getASpecifier().toString()
|
||||||
select interesting(e), e, name, specifier
|
|
|
||||||
|
s, ", "
|
||||||
|
) and
|
||||||
|
specifiers != ""
|
||||||
|
select interesting(e), e, name, specifiers
|
||||||
|
|||||||
@@ -1,3 +1,22 @@
|
|||||||
|
| cpp20.cpp:17:28:17:28 | (unnamed parameter 0) | file://:0:0:0:0 | const T | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:17:28:17:28 | (unnamed parameter 0) | file://:0:0:0:0 | const char | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:17:28:17:28 | (unnamed parameter 0) | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:24:24:24:24 | (unnamed parameter 0) | file://:0:0:0:0 | const T | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:40:47:40:47 | (unnamed parameter 0) | file://:0:0:0:0 | const T | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:40:47:40:47 | (unnamed parameter 0) | file://:0:0:0:0 | const char | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:40:47:40:47 | (unnamed parameter 0) | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:51:29:51:29 | (unnamed parameter 0) | file://:0:0:0:0 | const char | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:51:29:51:29 | (unnamed parameter 0) | file://:0:0:0:0 | const char | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:51:29:51:29 | (unnamed parameter 0) | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:51:29:51:29 | (unnamed parameter 0) | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:51:38:51:38 | (unnamed parameter 1) | file://:0:0:0:0 | const U | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:51:38:51:38 | (unnamed parameter 1) | file://:0:0:0:0 | const U | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:51:38:51:38 | (unnamed parameter 1) | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:51:38:51:38 | (unnamed parameter 1) | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:55:47:55:47 | (unnamed parameter 0) | file://:0:0:0:0 | const T | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:55:56:55:56 | (unnamed parameter 1) | file://:0:0:0:0 | const U | file://:0:0:0:0 | const |
|
||||||
|
| cpp20.cpp:64:23:64:32 | (unnamed parameter 0) | file://:0:0:0:0 | const char | file://:0:0:0:0 | const |
|
||||||
|
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | const double | file://:0:0:0:0 | const |
|
||||||
| specifiers2.c:18:21:18:23 | svi | file://:0:0:0:0 | volatile int | file://:0:0:0:0 | volatile |
|
| specifiers2.c:18:21:18:23 | svi | file://:0:0:0:0 | volatile int | file://:0:0:0:0 | volatile |
|
||||||
| specifiers2.c:19:11:19:12 | ci | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
|
| specifiers2.c:19:11:19:12 | ci | file://:0:0:0:0 | const int | file://:0:0:0:0 | const |
|
||||||
| specifiers2.c:21:34:21:34 | p | file://:0:0:0:0 | char *__restrict__ | file://:0:0:0:0 | restrict |
|
| specifiers2.c:21:34:21:34 | p | file://:0:0:0:0 | char *__restrict__ | file://:0:0:0:0 | restrict |
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
| cpp20.cpp:17:5:17:20 | TestExplicitBool | extern, public |
|
||||||
|
| cpp20.cpp:40:1:40:39 | TestExplicitBool2 | public |
|
||||||
|
| cpp20.cpp:40:23:40:23 | TestExplicitBool2 | public |
|
||||||
|
| cpp20.cpp:55:1:55:39 | TestExplicitBool3 | public |
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import cpp
|
||||||
|
|
||||||
|
from MemberFunction m, TemplateClass c, string specifiers
|
||||||
|
where
|
||||||
|
c.getAMember() = m and
|
||||||
|
specifiers = concat(string s | s = m.getASpecifier().getName() | s, ", ")
|
||||||
|
select m, specifiers
|
||||||
@@ -26,8 +26,11 @@
|
|||||||
| test.cpp:128:15:128:16 | v4 |
|
| test.cpp:128:15:128:16 | v4 |
|
||||||
| test.cpp:185:10:185:12 | cpy |
|
| test.cpp:185:10:185:12 | cpy |
|
||||||
| test.cpp:199:10:199:12 | cpy |
|
| test.cpp:199:10:199:12 | cpy |
|
||||||
| test.cpp:208:7:208:7 | a |
|
| test.cpp:213:7:213:7 | a |
|
||||||
| test.cpp:214:7:214:7 | a |
|
| test.cpp:219:7:219:7 | a |
|
||||||
|
| test.cpp:228:14:228:18 | data1 |
|
||||||
|
| test.cpp:236:14:236:18 | data1 |
|
||||||
|
| test.cpp:237:14:237:18 | data2 |
|
||||||
| test_free.cpp:11:10:11:10 | a |
|
| test_free.cpp:11:10:11:10 | a |
|
||||||
| test_free.cpp:14:10:14:10 | a |
|
| test_free.cpp:14:10:14:10 | a |
|
||||||
| test_free.cpp:16:10:16:10 | a |
|
| test_free.cpp:16:10:16:10 | a |
|
||||||
@@ -117,6 +120,12 @@
|
|||||||
| test_free.cpp:346:26:346:28 | ptr |
|
| test_free.cpp:346:26:346:28 | ptr |
|
||||||
| test_free.cpp:356:19:356:19 | a |
|
| test_free.cpp:356:19:356:19 | a |
|
||||||
| test_free.cpp:357:19:357:19 | a |
|
| test_free.cpp:357:19:357:19 | a |
|
||||||
|
| test_free.cpp:370:10:370:10 | a |
|
||||||
|
| test_free.cpp:373:10:373:10 | e |
|
||||||
|
| test_free.cpp:382:10:382:10 | i |
|
||||||
|
| test_free.cpp:383:10:383:10 | s |
|
||||||
|
| test_free.cpp:395:14:395:19 | buffer |
|
||||||
|
| test_free.cpp:424:10:424:16 | buffer2 |
|
||||||
| virtual.cpp:18:10:18:10 | a |
|
| virtual.cpp:18:10:18:10 | a |
|
||||||
| virtual.cpp:19:10:19:10 | c |
|
| virtual.cpp:19:10:19:10 | c |
|
||||||
| virtual.cpp:38:10:38:10 | b |
|
| virtual.cpp:38:10:38:10 | b |
|
||||||
|
|||||||
@@ -14,3 +14,5 @@
|
|||||||
| test_free.cpp:167:15:167:21 | call to realloc | This memory is never freed. |
|
| test_free.cpp:167:15:167:21 | call to realloc | This memory is never freed. |
|
||||||
| test_free.cpp:253:14:253:19 | call to malloc | This memory is never freed. |
|
| test_free.cpp:253:14:253:19 | call to malloc | This memory is never freed. |
|
||||||
| test_free.cpp:261:6:261:12 | new | This memory is never freed. |
|
| test_free.cpp:261:6:261:12 | new | This memory is never freed. |
|
||||||
|
| test_free.cpp:365:21:365:26 | call to malloc | This memory is never freed. |
|
||||||
|
| test_free.cpp:368:31:368:36 | call to malloc | This memory is never freed. |
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
edges
|
edges
|
||||||
| test.cpp:208:7:208:7 | pointer to free output argument | test.cpp:209:2:209:2 | a | provenance | |
|
| test.cpp:213:7:213:7 | pointer to free output argument | test.cpp:214:2:214:2 | a | provenance | |
|
||||||
| test.cpp:214:7:214:7 | pointer to free output argument | test.cpp:215:2:215:2 | a | provenance | |
|
| test.cpp:219:7:219:7 | pointer to free output argument | test.cpp:220:2:220:2 | a | provenance | |
|
||||||
|
| test.cpp:228:12:228:12 | *p [post update] [data1] | test.cpp:229:2:229:2 | *p [data1] | provenance | |
|
||||||
|
| test.cpp:228:14:228:18 | pointer to operator delete[] output argument | test.cpp:228:12:228:12 | *p [post update] [data1] | provenance | |
|
||||||
|
| test.cpp:229:2:229:2 | *p [data1] | test.cpp:229:4:229:8 | data1 | provenance | |
|
||||||
| test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:12:5:12:5 | a | provenance | |
|
| test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:12:5:12:5 | a | provenance | |
|
||||||
| test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:13:5:13:6 | * ... | provenance | |
|
| test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:13:5:13:6 | * ... | provenance | |
|
||||||
| test_free.cpp:42:27:42:27 | pointer to free output argument | test_free.cpp:45:5:45:5 | a | provenance | |
|
| test_free.cpp:42:27:42:27 | pointer to free output argument | test_free.cpp:45:5:45:5 | a | provenance | |
|
||||||
@@ -33,10 +36,14 @@ edges
|
|||||||
| test_free.cpp:322:12:322:12 | pointer to operator delete output argument | test_free.cpp:324:5:324:6 | * ... | provenance | |
|
| test_free.cpp:322:12:322:12 | pointer to operator delete output argument | test_free.cpp:324:5:324:6 | * ... | provenance | |
|
||||||
| test_free.cpp:331:12:331:12 | pointer to operator delete output argument | test_free.cpp:332:5:332:6 | * ... | provenance | |
|
| test_free.cpp:331:12:331:12 | pointer to operator delete output argument | test_free.cpp:332:5:332:6 | * ... | provenance | |
|
||||||
nodes
|
nodes
|
||||||
| test.cpp:208:7:208:7 | pointer to free output argument | semmle.label | pointer to free output argument |
|
| test.cpp:213:7:213:7 | pointer to free output argument | semmle.label | pointer to free output argument |
|
||||||
| test.cpp:209:2:209:2 | a | semmle.label | a |
|
| test.cpp:214:2:214:2 | a | semmle.label | a |
|
||||||
| test.cpp:214:7:214:7 | pointer to free output argument | semmle.label | pointer to free output argument |
|
| test.cpp:219:7:219:7 | pointer to free output argument | semmle.label | pointer to free output argument |
|
||||||
| test.cpp:215:2:215:2 | a | semmle.label | a |
|
| test.cpp:220:2:220:2 | a | semmle.label | a |
|
||||||
|
| test.cpp:228:12:228:12 | *p [post update] [data1] | semmle.label | *p [post update] [data1] |
|
||||||
|
| test.cpp:228:14:228:18 | pointer to operator delete[] output argument | semmle.label | pointer to operator delete[] output argument |
|
||||||
|
| test.cpp:229:2:229:2 | *p [data1] | semmle.label | *p [data1] |
|
||||||
|
| test.cpp:229:4:229:8 | data1 | semmle.label | data1 |
|
||||||
| test_free.cpp:11:10:11:10 | pointer to free output argument | semmle.label | pointer to free output argument |
|
| test_free.cpp:11:10:11:10 | pointer to free output argument | semmle.label | pointer to free output argument |
|
||||||
| test_free.cpp:12:5:12:5 | a | semmle.label | a |
|
| test_free.cpp:12:5:12:5 | a | semmle.label | a |
|
||||||
| test_free.cpp:13:5:13:6 | * ... | semmle.label | * ... |
|
| test_free.cpp:13:5:13:6 | * ... | semmle.label | * ... |
|
||||||
@@ -88,8 +95,9 @@ nodes
|
|||||||
| test_free.cpp:332:5:332:6 | * ... | semmle.label | * ... |
|
| test_free.cpp:332:5:332:6 | * ... | semmle.label | * ... |
|
||||||
subpaths
|
subpaths
|
||||||
#select
|
#select
|
||||||
| test.cpp:209:2:209:2 | a | test.cpp:208:7:208:7 | pointer to free output argument | test.cpp:209:2:209:2 | a | Memory may have been previously freed by $@. | test.cpp:208:2:208:5 | call to free | call to free |
|
| test.cpp:214:2:214:2 | a | test.cpp:213:7:213:7 | pointer to free output argument | test.cpp:214:2:214:2 | a | Memory may have been previously freed by $@. | test.cpp:213:2:213:5 | call to free | call to free |
|
||||||
| test.cpp:215:2:215:2 | a | test.cpp:214:7:214:7 | pointer to free output argument | test.cpp:215:2:215:2 | a | Memory may have been previously freed by $@. | test.cpp:214:2:214:5 | call to free | call to free |
|
| test.cpp:220:2:220:2 | a | test.cpp:219:7:219:7 | pointer to free output argument | test.cpp:220:2:220:2 | a | Memory may have been previously freed by $@. | test.cpp:219:2:219:5 | call to free | call to free |
|
||||||
|
| test.cpp:229:4:229:8 | data1 | test.cpp:228:14:228:18 | pointer to operator delete[] output argument | test.cpp:229:4:229:8 | data1 | Memory may have been previously freed by $@. | test.cpp:228:2:228:18 | delete[] | delete[] |
|
||||||
| test_free.cpp:12:5:12:5 | a | test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:12:5:12:5 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
|
| test_free.cpp:12:5:12:5 | a | test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:12:5:12:5 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
|
||||||
| test_free.cpp:13:5:13:6 | * ... | test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:13:5:13:6 | * ... | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
|
| test_free.cpp:13:5:13:6 | * ... | test_free.cpp:11:10:11:10 | pointer to free output argument | test_free.cpp:13:5:13:6 | * ... | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
|
||||||
| test_free.cpp:45:5:45:5 | a | test_free.cpp:42:27:42:27 | pointer to free output argument | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
|
| test_free.cpp:45:5:45:5 | a | test_free.cpp:42:27:42:27 | pointer to free output argument | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
|
||||||
|
|||||||
@@ -201,6 +201,11 @@ void test_strndupa_dealloc() {
|
|||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
|
struct DataPair {
|
||||||
|
char *data1;
|
||||||
|
char *data2;
|
||||||
|
};
|
||||||
|
|
||||||
void test_reassignment() {
|
void test_reassignment() {
|
||||||
char *a = (char *)malloc(128);
|
char *a = (char *)malloc(128);
|
||||||
char *b = (char *)malloc(128);
|
char *b = (char *)malloc(128);
|
||||||
@@ -213,4 +218,21 @@ void test_reassignment() {
|
|||||||
|
|
||||||
free(a);
|
free(a);
|
||||||
a[0] = 0; // BAD
|
a[0] = 0; // BAD
|
||||||
|
|
||||||
|
DataPair p;
|
||||||
|
p.data1 = new char[128];
|
||||||
|
p.data2 = new char[128];
|
||||||
|
p.data1[0] = 0; // GOOD
|
||||||
|
p.data2[0] = 0; // GOOD
|
||||||
|
|
||||||
|
delete [] p.data1;
|
||||||
|
p.data1[0] = 0; // BAD
|
||||||
|
p.data2[0] = 0; // GOOD
|
||||||
|
|
||||||
|
p.data1 = new char[128];
|
||||||
|
p.data1[0] = 0; // GOOD
|
||||||
|
p.data2[0] = 0; // GOOD
|
||||||
|
|
||||||
|
delete [] p.data1;
|
||||||
|
delete [] p.data2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -356,3 +356,73 @@ void test(E* e) {
|
|||||||
free(e->ec[0].a);
|
free(e->ec[0].a);
|
||||||
free(e->ec[1].a); // GOOD
|
free(e->ec[1].a); // GOOD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
void test_return_by_parameter(int **out_i, MyStruct **out_ms) {
|
||||||
|
int *a = (int *)malloc(sizeof(int)); // GOOD (freed)
|
||||||
|
int *b = (int *)malloc(sizeof(int)); // GOOD (out parameter)
|
||||||
|
int *d = (int *)malloc(sizeof(int)); // BAD (not freed)
|
||||||
|
MyStruct *e = (MyStruct *)malloc(sizeof(MyStruct)); // GOOD (freed)
|
||||||
|
MyStruct *f = (MyStruct *)malloc(sizeof(MyStruct)); // GOOD (out parameter)
|
||||||
|
MyStruct *h = (MyStruct *)malloc(sizeof(MyStruct)); // BAD (not freed)
|
||||||
|
|
||||||
|
free(a);
|
||||||
|
*out_i = b;
|
||||||
|
|
||||||
|
free(e);
|
||||||
|
*out_ms = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_return_by_parameter_caller() {
|
||||||
|
int *i;
|
||||||
|
MyStruct *s;
|
||||||
|
|
||||||
|
test_return_by_parameter(&i, &s);
|
||||||
|
free(i);
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
class HasGetterAndFree {
|
||||||
|
public:
|
||||||
|
HasGetterAndFree() {
|
||||||
|
buffer = malloc(1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
~HasGetterAndFree() {
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *getBuffer() {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
class HasGetterNoFree {
|
||||||
|
public:
|
||||||
|
HasGetterNoFree() {
|
||||||
|
buffer = malloc(1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *getBuffer() {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
void testHasGetter() {
|
||||||
|
HasGetterAndFree hg;
|
||||||
|
void *buffer = hg.getBuffer(); // GOOD (freed in destructor)
|
||||||
|
|
||||||
|
HasGetterNoFree hg2;
|
||||||
|
void *buffer2 = hg2.getBuffer(); // GOOD (freed below)
|
||||||
|
free(buffer2);
|
||||||
|
|
||||||
|
HasGetterNoFree hg3;
|
||||||
|
void *buffer3 = hg3.getBuffer(); // BAD (not freed) [NOT DETECTED]
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,21 @@ edges
|
|||||||
| test.cpp:420:19:420:20 | scanf output argument | test.cpp:423:7:423:7 | i | provenance | |
|
| test.cpp:420:19:420:20 | scanf output argument | test.cpp:423:7:423:7 | i | provenance | |
|
||||||
| test.cpp:455:41:455:46 | sscanf output argument | test.cpp:460:6:460:10 | value | provenance | |
|
| test.cpp:455:41:455:46 | sscanf output argument | test.cpp:460:6:460:10 | value | provenance | |
|
||||||
| test.cpp:467:20:467:25 | scanf output argument | test.cpp:474:6:474:10 | value | provenance | |
|
| test.cpp:467:20:467:25 | scanf output argument | test.cpp:474:6:474:10 | value | provenance | |
|
||||||
|
| test.cpp:480:25:480:26 | scanf output argument | test.cpp:484:9:484:9 | i | provenance | |
|
||||||
|
| test.cpp:491:25:491:26 | scanf output argument | test.cpp:495:8:495:8 | i | provenance | |
|
||||||
|
| test.cpp:501:25:501:26 | scanf output argument | test.cpp:505:9:505:9 | i | provenance | |
|
||||||
|
| test.cpp:512:25:512:26 | scanf output argument | test.cpp:516:9:516:9 | i | provenance | |
|
||||||
|
| test.cpp:525:35:525:36 | sscanf output argument | test.cpp:527:8:527:8 | a | provenance | |
|
||||||
|
| test.cpp:525:35:525:36 | sscanf output argument | test.cpp:531:8:531:8 | a | provenance | |
|
||||||
|
| test.cpp:525:39:525:40 | sscanf output argument | test.cpp:528:8:528:8 | b | provenance | |
|
||||||
|
| test.cpp:525:39:525:40 | sscanf output argument | test.cpp:532:8:532:8 | b | provenance | |
|
||||||
|
| test.cpp:525:43:525:44 | sscanf output argument | test.cpp:533:8:533:8 | c | provenance | |
|
||||||
|
| test.cpp:541:35:541:36 | sscanf output argument | test.cpp:543:8:543:8 | d | provenance | |
|
||||||
|
| test.cpp:541:35:541:36 | sscanf output argument | test.cpp:548:8:548:8 | d | provenance | |
|
||||||
|
| test.cpp:541:39:541:40 | sscanf output argument | test.cpp:544:8:544:8 | e | provenance | |
|
||||||
|
| test.cpp:541:39:541:40 | sscanf output argument | test.cpp:549:8:549:8 | e | provenance | |
|
||||||
|
| test.cpp:541:43:541:44 | sscanf output argument | test.cpp:545:8:545:8 | f | provenance | |
|
||||||
|
| test.cpp:541:43:541:44 | sscanf output argument | test.cpp:550:8:550:8 | f | provenance | |
|
||||||
nodes
|
nodes
|
||||||
| test.cpp:34:15:34:16 | scanf output argument | semmle.label | scanf output argument |
|
| test.cpp:34:15:34:16 | scanf output argument | semmle.label | scanf output argument |
|
||||||
| test.cpp:35:7:35:7 | i | semmle.label | i |
|
| test.cpp:35:7:35:7 | i | semmle.label | i |
|
||||||
@@ -114,6 +129,31 @@ nodes
|
|||||||
| test.cpp:460:6:460:10 | value | semmle.label | value |
|
| test.cpp:460:6:460:10 | value | semmle.label | value |
|
||||||
| test.cpp:467:20:467:25 | scanf output argument | semmle.label | scanf output argument |
|
| test.cpp:467:20:467:25 | scanf output argument | semmle.label | scanf output argument |
|
||||||
| test.cpp:474:6:474:10 | value | semmle.label | value |
|
| test.cpp:474:6:474:10 | value | semmle.label | value |
|
||||||
|
| test.cpp:480:25:480:26 | scanf output argument | semmle.label | scanf output argument |
|
||||||
|
| test.cpp:484:9:484:9 | i | semmle.label | i |
|
||||||
|
| test.cpp:491:25:491:26 | scanf output argument | semmle.label | scanf output argument |
|
||||||
|
| test.cpp:495:8:495:8 | i | semmle.label | i |
|
||||||
|
| test.cpp:501:25:501:26 | scanf output argument | semmle.label | scanf output argument |
|
||||||
|
| test.cpp:505:9:505:9 | i | semmle.label | i |
|
||||||
|
| test.cpp:512:25:512:26 | scanf output argument | semmle.label | scanf output argument |
|
||||||
|
| test.cpp:516:9:516:9 | i | semmle.label | i |
|
||||||
|
| test.cpp:525:35:525:36 | sscanf output argument | semmle.label | sscanf output argument |
|
||||||
|
| test.cpp:525:39:525:40 | sscanf output argument | semmle.label | sscanf output argument |
|
||||||
|
| test.cpp:525:43:525:44 | sscanf output argument | semmle.label | sscanf output argument |
|
||||||
|
| test.cpp:527:8:527:8 | a | semmle.label | a |
|
||||||
|
| test.cpp:528:8:528:8 | b | semmle.label | b |
|
||||||
|
| test.cpp:531:8:531:8 | a | semmle.label | a |
|
||||||
|
| test.cpp:532:8:532:8 | b | semmle.label | b |
|
||||||
|
| test.cpp:533:8:533:8 | c | semmle.label | c |
|
||||||
|
| test.cpp:541:35:541:36 | sscanf output argument | semmle.label | sscanf output argument |
|
||||||
|
| test.cpp:541:39:541:40 | sscanf output argument | semmle.label | sscanf output argument |
|
||||||
|
| test.cpp:541:43:541:44 | sscanf output argument | semmle.label | sscanf output argument |
|
||||||
|
| test.cpp:543:8:543:8 | d | semmle.label | d |
|
||||||
|
| test.cpp:544:8:544:8 | e | semmle.label | e |
|
||||||
|
| test.cpp:545:8:545:8 | f | semmle.label | f |
|
||||||
|
| test.cpp:548:8:548:8 | d | semmle.label | d |
|
||||||
|
| test.cpp:549:8:549:8 | e | semmle.label | e |
|
||||||
|
| test.cpp:550:8:550:8 | f | semmle.label | f |
|
||||||
subpaths
|
subpaths
|
||||||
#select
|
#select
|
||||||
| test.cpp:35:7:35:7 | i | test.cpp:34:15:34:16 | scanf output argument | test.cpp:35:7:35:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:34:3:34:7 | call to scanf | call to scanf |
|
| test.cpp:35:7:35:7 | i | test.cpp:34:15:34:16 | scanf output argument | test.cpp:35:7:35:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:34:3:34:7 | call to scanf | call to scanf |
|
||||||
@@ -134,3 +174,6 @@ subpaths
|
|||||||
| test.cpp:423:7:423:7 | i | test.cpp:420:19:420:20 | scanf output argument | test.cpp:423:7:423:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:420:7:420:11 | call to scanf | call to scanf |
|
| test.cpp:423:7:423:7 | i | test.cpp:420:19:420:20 | scanf output argument | test.cpp:423:7:423:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:420:7:420:11 | call to scanf | call to scanf |
|
||||||
| test.cpp:460:6:460:10 | value | test.cpp:455:41:455:46 | sscanf output argument | test.cpp:460:6:460:10 | value | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:455:12:455:17 | call to sscanf | call to sscanf |
|
| test.cpp:460:6:460:10 | value | test.cpp:455:41:455:46 | sscanf output argument | test.cpp:460:6:460:10 | value | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:455:12:455:17 | call to sscanf | call to sscanf |
|
||||||
| test.cpp:474:6:474:10 | value | test.cpp:467:20:467:25 | scanf output argument | test.cpp:474:6:474:10 | value | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:467:8:467:12 | call to scanf | call to scanf |
|
| test.cpp:474:6:474:10 | value | test.cpp:467:20:467:25 | scanf output argument | test.cpp:474:6:474:10 | value | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:467:8:467:12 | call to scanf | call to scanf |
|
||||||
|
| test.cpp:484:9:484:9 | i | test.cpp:480:25:480:26 | scanf output argument | test.cpp:484:9:484:9 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:480:13:480:17 | call to scanf | call to scanf |
|
||||||
|
| test.cpp:495:8:495:8 | i | test.cpp:491:25:491:26 | scanf output argument | test.cpp:495:8:495:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:491:13:491:17 | call to scanf | call to scanf |
|
||||||
|
| test.cpp:545:8:545:8 | f | test.cpp:541:43:541:44 | sscanf output argument | test.cpp:545:8:545:8 | f | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 3. | test.cpp:541:10:541:15 | call to sscanf | call to sscanf |
|
||||||
|
|||||||
@@ -473,3 +473,83 @@ void check_for_negative_test() {
|
|||||||
}
|
}
|
||||||
use(value);
|
use(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void multiple_checks() {
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int res = scanf("%d", &i);
|
||||||
|
|
||||||
|
if (res >= 0) {
|
||||||
|
if (res != 0) {
|
||||||
|
use(i); // GOOD: checks return value [FALSE POSITIVE]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int res = scanf("%d", &i);
|
||||||
|
|
||||||
|
if (res < 0) return;
|
||||||
|
if (res != 0) {
|
||||||
|
use(i); // GOOD: checks return value [FALSE POSITIVE]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int res = scanf("%d", &i);
|
||||||
|
|
||||||
|
if (res >= 1) {
|
||||||
|
if (res != 0) {
|
||||||
|
use(i); // GOOD: checks return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int res = scanf("%d", &i);
|
||||||
|
|
||||||
|
if (res == 1) {
|
||||||
|
if (res != 0) {
|
||||||
|
use(i); // GOOD: checks return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void switch_cases(const char *data) {
|
||||||
|
float a, b, c;
|
||||||
|
|
||||||
|
switch (sscanf(data, "%f %f %f", &a, &b, &c)) {
|
||||||
|
case 2:
|
||||||
|
use(a); // GOOD
|
||||||
|
use(b); // GOOD
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
use(a); // GOOD
|
||||||
|
use(b); // GOOD
|
||||||
|
use(c); // GOOD
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
float d, e, f;
|
||||||
|
|
||||||
|
switch (sscanf(data, "%f %f %f", &d, &e, &f)) {
|
||||||
|
case 2:
|
||||||
|
use(d); // GOOD
|
||||||
|
use(e); // GOOD
|
||||||
|
use(f); // BAD
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
use(d); // GOOD
|
||||||
|
use(e); // GOOD
|
||||||
|
use(f); // GOOD
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user