Skip to content

Commit 503830a

Browse files
Implement Concurrency8 package
1 parent 5c5bb64 commit 503830a

File tree

56 files changed

+1964
-209
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1964
-209
lines changed

c/cert/src/rules/CON34-C/AppropriateThreadObjectStorageDurations.ql

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,39 @@
1414

1515
import cpp
1616
import codingstandards.c.cert
17+
import codingstandards.c.Objects
1718
import codingstandards.cpp.Concurrency
1819
import codingstandards.cpp.dataflow.TaintTracking
1920
import codingstandards.cpp.dataflow.DataFlow
2021
import semmle.code.cpp.commons.Alloc
2122

22-
from C11ThreadCreateCall tcc, StackVariable sv, Expr arg, Expr acc
23+
from C11ThreadCreateCall tcc, Expr arg
2324
where
2425
not isExcluded(tcc, Concurrency4Package::appropriateThreadObjectStorageDurationsQuery()) and
2526
tcc.getArgument(2) = arg and
26-
sv.getAnAccess() = acc and
27-
// a stack variable that is given as an argument to a thread
28-
TaintTracking::localTaint(DataFlow::exprNode(acc), DataFlow::exprNode(arg)) and
29-
// or isn't one of the allowed usage patterns
30-
not exists(Expr mfc |
31-
isAllocationExpr(mfc) and
32-
sv.getAnAssignedValue() = mfc and
33-
acc.getAPredecessor*() = mfc
34-
) and
35-
not exists(TSSGetFunctionCall tsg, TSSSetFunctionCall tss, DataFlow::Node src |
36-
sv.getAnAssignedValue() = tsg and
37-
acc.getAPredecessor*() = tsg and
38-
// there should be dataflow from somewhere (the same somewhere)
39-
// into each of the first arguments
40-
DataFlow::localFlow(src, DataFlow::exprNode(tsg.getArgument(0))) and
41-
DataFlow::localFlow(src, DataFlow::exprNode(tss.getArgument(0)))
27+
(
28+
exists(ObjectIdentity obj, Expr acc |
29+
obj.getASubobjectAccess() = acc and
30+
obj.getStorageDuration().isAutomatic() and
31+
exists(DataFlow::Node addrNode |
32+
(
33+
addrNode = DataFlow::exprNode(any(AddressOfExpr e | e.getOperand() = acc))
34+
or
35+
addrNode = DataFlow::exprNode(acc) and exists(ArrayToPointerConversion c | c.getExpr() = acc)
36+
) and
37+
TaintTracking::localTaint(addrNode, DataFlow::exprNode(arg))
38+
)
39+
)
40+
or
41+
// TODO: Remove/replace with tss_t type check, see #801.
42+
exists(TSSGetFunctionCall tsg |
43+
TaintTracking::localTaint(DataFlow::exprNode(tsg), DataFlow::exprNode(arg)) and
44+
not exists(TSSSetFunctionCall tss, DataFlow::Node src |
45+
// there should be dataflow from somewhere (the same somewhere)
46+
// into each of the first arguments
47+
DataFlow::localFlow(src, DataFlow::exprNode(tsg.getArgument(0))) and
48+
DataFlow::localFlow(src, DataFlow::exprNode(tss.getArgument(0)))
49+
)
50+
)
4251
)
4352
select tcc, "$@ not declared with appropriate storage duration", arg, "Shared object"

c/cert/src/rules/DCL30-C/AppropriateStorageDurationsFunctionReturn.ql

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@
1313

1414
import cpp
1515
import codingstandards.c.cert
16+
import codingstandards.c.Objects
1617
import codingstandards.cpp.dataflow.DataFlow
1718

18-
class Source extends StackVariable {
19-
Source() { not this instanceof Parameter }
19+
class Source extends Expr {
20+
ObjectIdentity rootObject;
21+
Source() {
22+
rootObject.getStorageDuration().isAutomatic()
23+
and this = rootObject.getASubobjectAddressExpr()
24+
}
2025
}
2126

2227
class Sink extends DataFlow::Node {
@@ -40,7 +45,7 @@ from DataFlow::Node src, DataFlow::Node sink
4045
where
4146
not isExcluded(sink.asExpr(),
4247
Declarations8Package::appropriateStorageDurationsFunctionReturnQuery()) and
43-
exists(Source s | src.asExpr() = s.getAnAccess()) and
48+
exists(Source s | src.asExpr() = s) and
4449
sink instanceof Sink and
4550
DataFlow::localFlow(src, sink)
4651
select sink, "$@ with automatic storage may be accessible outside of its lifetime.", src,

c/cert/src/rules/EXP35-C/DoNotModifyObjectsWithTemporaryLifetime.ql

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,13 @@
1313

1414
import cpp
1515
import codingstandards.c.cert
16-
import codingstandards.cpp.lifetimes.CLifetimes
16+
import codingstandards.c.Objects
1717

1818
// Note: Undefined behavior is possible regardless of whether the accessed field from the returned
1919
// struct is an array or a scalar (i.e. arithmetic and pointer types) member, according to the standard.
20-
from FieldAccess fa, FunctionCall fc
20+
from FieldAccess fa, TemporaryObjectIdentity tempObject
2121
where
2222
not isExcluded(fa, InvalidMemory2Package::doNotModifyObjectsWithTemporaryLifetimeQuery()) and
23-
not fa.getQualifier().isLValue() and
24-
fa.getQualifier().getUnconverted() = fc and
25-
fa.getQualifier().getUnconverted().getUnspecifiedType() instanceof StructOrUnionTypeWithArrayField
26-
select fa, "Field access on $@ qualifier occurs after its temporary object lifetime.", fc,
27-
"function call"
23+
fa.getQualifier().getUnconverted() = tempObject
24+
select fa, "Field access on $@ qualifier occurs after its temporary object lifetime.", tempObject,
25+
"temporary object"

c/cert/src/rules/MEM33-C/AllocStructsWithAFlexibleArrayMemberDynamically.ql

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
import cpp
1515
import codingstandards.c.cert
1616
import codingstandards.c.Variable
17+
import codingstandards.c.Objects
1718
import semmle.code.cpp.models.interfaces.Allocation
1819
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
1920

2021
abstract class FlexibleArrayAlloc extends Element {
2122
/**
2223
* Returns the `Variable` being allocated.
2324
*/
24-
abstract Variable getVariable();
25+
abstract Element getReportElement();
2526
}
2627

2728
/**
@@ -53,18 +54,25 @@ class FlexibleArrayStructDynamicAlloc extends FlexibleArrayAlloc, FunctionCall {
5354
)
5455
}
5556

56-
override Variable getVariable() { result = v }
57+
override Element getReportElement() { result = v }
5758
}
5859

5960
/**
6061
* A `Variable` of type `FlexibleArrayStructType` that is not allocated dynamically.
6162
*/
62-
class FlexibleArrayNonDynamicAlloc extends FlexibleArrayAlloc, Variable {
63+
class FlexibleArrayNonDynamicAlloc extends FlexibleArrayAlloc {
64+
ObjectIdentity object;
6365
FlexibleArrayNonDynamicAlloc() {
64-
this.getUnspecifiedType().getUnspecifiedType() instanceof FlexibleArrayStructType
66+
this = object and
67+
not object.getStorageDuration().isAllocated() and
68+
// Exclude temporaries. Though they should violate this rule, in practice these results are
69+
// often spurious and redundant, such as (*x = *x) which creates an unused temporary object.
70+
not object.hasTemporaryLifetime() and
71+
object.getType().getUnspecifiedType() instanceof FlexibleArrayStructType
72+
and not exists(Variable v | v.getInitializer().getExpr() = this)
6573
}
6674

67-
override Variable getVariable() { result = this }
75+
override Element getReportElement() { result = object }
6876
}
6977

7078
from FlexibleArrayAlloc alloc, string message
@@ -77,4 +85,4 @@ where
7785
alloc instanceof FlexibleArrayNonDynamicAlloc and
7886
message = "$@ contains a flexible array member but is not dynamically allocated."
7987
)
80-
select alloc, message, alloc.getVariable(), alloc.getVariable().getName()
88+
select alloc, message, alloc.getReportElement(), alloc.getReportElement().toString()
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
| test.c:65:18:65:18 | a | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:65:9:65:14 | call to get_s1 | function call |
2-
| test.c:67:18:67:19 | s1 | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:67:9:67:14 | call to get_s3 | function call |
3-
| test.c:68:18:68:19 | i1 | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:68:9:68:14 | call to get_s3 | function call |
4-
| test.c:69:18:69:21 | af12 | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:69:9:69:14 | call to get_s4 | function call |
1+
| test.c:65:18:65:18 | a | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:65:9:65:14 | call to get_s1 | temporary object |
2+
| test.c:67:18:67:19 | s1 | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:67:9:67:14 | call to get_s3 | temporary object |
3+
| test.c:68:18:68:19 | i1 | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:68:9:68:14 | call to get_s3 | temporary object |
4+
| test.c:69:18:69:21 | af12 | Field access on $@ qualifier occurs after its temporary object lifetime. | test.c:69:9:69:14 | call to get_s4 | temporary object |
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import cpp
2+
3+
newtype TIdentifierLinkage =
4+
TIdentifierLinkageExternal() or
5+
TIdentifierLinkageInternal() or
6+
TIdentifierLinkageNone()
7+
8+
/**
9+
* In C, identifiers have internal linkage, or external linkage, or no linkage (6.2.2.1).
10+
*
11+
* The linkage of an identifier is used to, among other things, determine the storage duration
12+
* and/or lifetime of that identifier. Storage durations and lifetimes are often used to define
13+
* rules in the various coding standards.
14+
*/
15+
class IdentifierLinkage extends TIdentifierLinkage {
16+
predicate isExternal() { this = TIdentifierLinkageExternal() }
17+
18+
predicate isInternal() { this = TIdentifierLinkageInternal() }
19+
20+
predicate isNone() { this = TIdentifierLinkageNone() }
21+
22+
string toString() {
23+
this.isExternal() and result = "external linkage"
24+
or
25+
this.isInternal() and result = "internal linkage"
26+
or
27+
this.isNone() and result = "no linkage"
28+
}
29+
}
30+
31+
/**
32+
* Determine the linkage of a variable: external, or static, or none.
33+
*
34+
* The linkage of a variable is determined by its scope and storage class. Note that other types of
35+
* identifiers (e.g. functions) may also have linkage, but that behavior is not covered in this
36+
* predicate.
37+
*/
38+
IdentifierLinkage linkageOfVariable(Variable v) {
39+
// 6.2.2.3, file scope identifiers marked static have internal linkage.
40+
v.isTopLevel() and v.isStatic() and result.isInternal()
41+
or
42+
// 6.2.2.4 describes generally non-static file scope identifiers, which have external linkage.
43+
v.isTopLevel() and not v.isStatic() and result.isExternal()
44+
or
45+
// Note: Not all identifiers have linkage, see 6.2.2.6
46+
not v.isTopLevel() and result.isNone()
47+
}

0 commit comments

Comments
 (0)