Skip to content

Commit ab43602

Browse files
committed
Add Rule-19-1 and converted M0-2-1 to shared query
1 parent 892fab6 commit ab43602

20 files changed

+263
-55
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| test.c:9:3:9:11 | ... = ... | An object $@ assigned to overlapping object $@. | test.c:9:5:9:5 | l | l | test.c:9:11:9:11 | i | i |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// GENERATED FILE - DO NOT MODIFY
2+
import codingstandards.cpp.rules.overlappingobjectassignment.OverlappingObjectAssignment
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <stdint.h>
2+
3+
void f(void) {
4+
union {
5+
int i;
6+
long l;
7+
} u = {0};
8+
9+
u.l = u.i; // NON_COMPLIANT
10+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* @id c/misra/object-assigned-to-an-overlapping-object
3+
* @name RULE-19-1: An object shall not be assigned to an overlapping object
4+
* @description An object shall not be assigned to an overlapping object.
5+
* @kind problem
6+
* @precision high
7+
* @problem.severity error
8+
* @tags external/misra/id/rule-19-1
9+
* correctness
10+
* external/misra/obligation/mandatory
11+
*/
12+
13+
import cpp
14+
import codingstandards.c.misra
15+
import codingstandards.cpp.rules.overlappingobjectassignment.OverlappingObjectAssignment
16+
17+
class ObjectAssignedToAnOverlappingObjectQuery extends OverlappingObjectAssignmentSharedQuery {
18+
ObjectAssignedToAnOverlappingObjectQuery() {
19+
this = Contracts7Package::objectAssignedToAnOverlappingObjectQuery()
20+
}
21+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
* @id c/misra/object-copied-to-an-overlapping-object
3+
* @name RULE-19-1: An object shall not be copied to an overlapping object
4+
* @description An object shall not be copied to an overlapping object.
5+
* @kind problem
6+
* @precision high
7+
* @problem.severity error
8+
* @tags external/misra/id/rule-19-1
9+
* correctness
10+
* external/misra/obligation/mandatory
11+
*/
12+
13+
import cpp
14+
import codingstandards.c.misra
15+
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
16+
import semmle.code.cpp.dataflow.DataFlow
17+
18+
/**
19+
* Models calls to memcpy on overlapping objects
20+
*/
21+
class MemcpyCall extends Locatable {
22+
Expr src;
23+
Expr dst;
24+
25+
MemcpyCall() {
26+
this.(MacroInvocation).getMacroName() = "memcpy" and
27+
src = this.(MacroInvocation).getExpr().getChild(1) and
28+
dst = this.(MacroInvocation).getExpr().getChild(0)
29+
or
30+
this.(FunctionCall).getTarget().hasGlobalName("memcpy") and
31+
src = this.(FunctionCall).getArgument(1) and
32+
dst = this.(FunctionCall).getArgument(0)
33+
}
34+
35+
Expr getSrc() { result = src }
36+
37+
Expr getDst() { result = dst }
38+
39+
Expr getBase(Expr e) {
40+
result =
41+
[
42+
e.(VariableAccess), e.(PointerAddExpr).getLeftOperand(),
43+
e.(AddressOfExpr).getOperand().(ArrayExpr).getArrayBase()
44+
]
45+
}
46+
47+
int getOffset(Expr e) {
48+
result =
49+
[
50+
e.(PointerAddExpr).getRightOperand().getValue().toInt(),
51+
e.(AddressOfExpr).getOperand().(ArrayExpr).getArrayOffset().getValue().toInt()
52+
]
53+
or
54+
e instanceof VariableAccess and result = 0
55+
}
56+
57+
// maximum amount of element copied
58+
int getCount() {
59+
result =
60+
upperBound([this.(MacroInvocation).getExpr().getChild(2), this.(FunctionCall).getArgument(2)])
61+
}
62+
63+
// source and destination overlap
64+
predicate overlap() {
65+
globalValueNumber(this.getBase(src)) = globalValueNumber(this.getBase(dst)) and
66+
exists(int dstStart, int dstEnd, int srcStart, int srcEnd |
67+
dstStart = this.getOffset(dst) and
68+
dstEnd = dstStart + this.getCount() - 1 and
69+
srcStart = this.getOffset(src) and
70+
srcEnd = srcStart + this.getCount() - 1 and
71+
(
72+
srcStart >= dstStart and srcEnd <= dstEnd
73+
or
74+
srcStart <= dstStart and srcEnd > dstStart
75+
or
76+
srcStart < dstEnd and srcEnd >= dstStart
77+
) and
78+
// Exception 1: exact overlap and compatible type
79+
not (
80+
srcStart = dstStart and
81+
srcEnd = dstEnd and
82+
this.getBase(src).getUnspecifiedType() = this.getBase(dst).getUnspecifiedType()
83+
)
84+
)
85+
}
86+
}
87+
88+
from MemcpyCall memcpy
89+
where
90+
not isExcluded(memcpy, Contracts7Package::objectCopiedToAnOverlappingObjectQuery()) and
91+
memcpy.overlap()
92+
select memcpy, "The object to copy $@ overlaps the object to copy $@.", memcpy.getSrc(), "from",
93+
memcpy.getDst(), "to"

c/misra/test/rules/RULE-12-2/test.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ void f1() {
2121
ul << 64; // NON_COMPLIANT
2222

2323
// 1UL essential type is essentially unsigned char
24-
1UL << 7; // COMPLIANT
25-
1UL << 8; // NON_COMPLIANT
26-
1UL << 64; // NON_COMPLIANT
24+
1UL << 7; // COMPLIANT
25+
1UL << 8; // NON_COMPLIANT
26+
1UL << 64; // NON_COMPLIANT
2727

2828
// ULONG_MAX essential type is essentially unsigned long
2929
ULONG_MAX << 8; // COMPLIANT
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
c/common/test/rules/overlappingobjectassignment/OverlappingObjectAssignment.ql
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
| test.c:5:3:5:8 | call to memcpy | The object to copy $@ overlaps the object to copy $@. | test.c:5:17:5:21 | & ... | from | test.c:5:10:5:14 | & ... | to |
2+
| test.c:7:3:7:8 | call to memcpy | The object to copy $@ overlaps the object to copy $@. | test.c:7:17:7:21 | & ... | from | test.c:7:10:7:14 | & ... | to |
3+
| test.c:8:3:8:8 | call to memcpy | The object to copy $@ overlaps the object to copy $@. | test.c:8:17:8:17 | o | from | test.c:8:10:8:14 | ... + ... | to |
4+
| test.c:10:3:10:8 | call to memcpy | The object to copy $@ overlaps the object to copy $@. | test.c:10:17:10:21 | ... + ... | from | test.c:10:10:10:14 | ... + ... | to |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rules/RULE-19-1/ObjectCopiedToAnOverlappingObject.ql

c/misra/test/rules/RULE-19-1/test.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <string.h>
2+
3+
int o[10];
4+
void g(void) {
5+
memcpy(&o[1], &o[0], 2); // NON_COMPLIANT
6+
memcpy(&o[2], &o[0], 2); // COMPLIANT
7+
memcpy(&o[2], &o[1], 2); // NON_COMPLIANT
8+
memcpy(o + 1, o, 2); // NON_COMPLIANT
9+
memcpy(o + 2, o, 2); // COMPLIANT
10+
memcpy(o + 2, o + 1, 2); // NON_COMPLIANT
11+
12+
// Exception 1
13+
int *p = &o[0];
14+
int *q = &o[0];
15+
16+
*p = *q; // COMPLIANT
17+
memcpy(&o[0], &o[0], 2); // COMPLIANT
18+
memcpy(o, o, 2); // COMPLIANT
19+
20+
// Exception 2
21+
memmove(&o[1], &o[0], 2u * sizeof(o[0])); // COMPLIANT
22+
}

cpp/autosar/src/rules/M0-2-1/ObjectAssignedToAnOverlappingObject.ql

Lines changed: 5 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,46 +12,12 @@
1212
* external/autosar/obligation/required
1313
*/
1414

15-
//Assignment between different active members of same union instance
1615
import cpp
1716
import codingstandards.cpp.autosar
18-
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
17+
import codingstandards.cpp.rules.overlappingobjectassignment.OverlappingObjectAssignment
1918

20-
VariableAccess getAQualifier(VariableAccess va) { result = va.getQualifier+() }
21-
22-
int getAccessByteOffset(FieldAccess fa) {
23-
not fa.getQualifier() instanceof FieldAccess and result = fa.getTarget().getByteOffset()
24-
or
25-
result = fa.getTarget().getByteOffset() + getAccessByteOffset(fa.getQualifier())
26-
}
27-
28-
predicate overlaps(FieldAccess fa1, FieldAccess fa2) {
29-
exists(int startfa1, int endfa1, int startfa2, int endfa2 |
30-
startfa1 = getAccessByteOffset(fa1) and
31-
endfa1 = startfa1 + fa1.getTarget().getType().getSize() - 1 and
32-
startfa2 = getAccessByteOffset(fa2) and
33-
endfa2 = startfa2 + fa2.getTarget().getType().getSize() - 1
34-
|
35-
startfa1 = startfa2 and endfa1 = endfa2
36-
or
37-
startfa1 > startfa2 and endfa1 < endfa2
38-
or
39-
startfa1 < startfa2 and endfa1 < endfa2 and endfa1 > startfa2
40-
or
41-
startfa1 > startfa2 and endfa1 > endfa2 and startfa1 < endfa2
42-
)
19+
class ObjectAssignedToAnOverlappingObjectQuery extends OverlappingObjectAssignmentSharedQuery {
20+
ObjectAssignedToAnOverlappingObjectQuery() {
21+
this = RepresentationPackage::objectAssignedToAnOverlappingObjectQuery()
22+
}
4323
}
44-
45-
from AssignExpr assignExpr, Expr lhs, Expr rhs, ValueFieldAccess valuelhs, ValueFieldAccess valuerhs
46-
where
47-
not isExcluded(assignExpr, RepresentationPackage::objectAssignedToAnOverlappingObjectQuery()) and
48-
lhs.getType() instanceof Union and
49-
rhs.getType() instanceof Union and
50-
lhs = getAQualifier(assignExpr.getLValue()) and
51-
rhs = getAQualifier(assignExpr.getRValue()) and
52-
globalValueNumber(lhs) = globalValueNumber(rhs) and
53-
valuerhs = assignExpr.getRValue() and
54-
valuelhs = assignExpr.getLValue() and // a.b.c == ((a.b).c)
55-
overlaps(valuelhs, valuerhs)
56-
select assignExpr, "An object $@ assigned to overlapping object $@.", valuelhs,
57-
valuelhs.getTarget().getName(), valuerhs, valuerhs.getTarget().getName()

cpp/autosar/test/rules/M0-2-1/ObjectAssignedToAnOverlappingObject.qlref

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cpp/common/test/rules/overlappingobjectassignment/OverlappingObjectAssignment.ql

cpp/common/src/codingstandards/cpp/exclusions/c/Contracts7.qll

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ newtype Contracts7Query =
77
TDoNotPassInvalidDataToTheAsctimeFunctionQuery() or
88
TDoNotCallVaArgOnAVaListThatHasAnIndeterminateValueQuery() or
99
TRightHandOperandOfAShiftRangeQuery() or
10-
TObjectAssignedOrCopiedToAnOverlappingObjectQuery()
10+
TObjectAssignedToAnOverlappingObjectQuery() or
11+
TObjectCopiedToAnOverlappingObjectQuery()
1112

1213
predicate isContracts7QueryMetadata(Query query, string queryId, string ruleId, string category) {
1314
query =
@@ -38,11 +39,20 @@ predicate isContracts7QueryMetadata(Query query, string queryId, string ruleId,
3839
category = "required"
3940
or
4041
query =
41-
// `Query` instance for the `objectAssignedOrCopiedToAnOverlappingObject` query
42-
Contracts7Package::objectAssignedOrCopiedToAnOverlappingObjectQuery() and
42+
// `Query` instance for the `objectAssignedToAnOverlappingObject` query
43+
Contracts7Package::objectAssignedToAnOverlappingObjectQuery() and
4344
queryId =
44-
// `@id` for the `objectAssignedOrCopiedToAnOverlappingObject` query
45-
"c/misra/object-assigned-or-copied-to-an-overlapping-object" and
45+
// `@id` for the `objectAssignedToAnOverlappingObject` query
46+
"c/misra/object-assigned-to-an-overlapping-object" and
47+
ruleId = "RULE-19-1" and
48+
category = "mandatory"
49+
or
50+
query =
51+
// `Query` instance for the `objectCopiedToAnOverlappingObject` query
52+
Contracts7Package::objectCopiedToAnOverlappingObjectQuery() and
53+
queryId =
54+
// `@id` for the `objectCopiedToAnOverlappingObject` query
55+
"c/misra/object-copied-to-an-overlapping-object" and
4656
ruleId = "RULE-19-1" and
4757
category = "mandatory"
4858
}
@@ -69,10 +79,17 @@ module Contracts7Package {
6979
TQueryC(TContracts7PackageQuery(TRightHandOperandOfAShiftRangeQuery()))
7080
}
7181

72-
Query objectAssignedOrCopiedToAnOverlappingObjectQuery() {
82+
Query objectAssignedToAnOverlappingObjectQuery() {
83+
//autogenerate `Query` type
84+
result =
85+
// `Query` type for `objectAssignedToAnOverlappingObject` query
86+
TQueryC(TContracts7PackageQuery(TObjectAssignedToAnOverlappingObjectQuery()))
87+
}
88+
89+
Query objectCopiedToAnOverlappingObjectQuery() {
7390
//autogenerate `Query` type
7491
result =
75-
// `Query` type for `objectAssignedOrCopiedToAnOverlappingObject` query
76-
TQueryC(TContracts7PackageQuery(TObjectAssignedOrCopiedToAnOverlappingObjectQuery()))
92+
// `Query` type for `objectCopiedToAnOverlappingObject` query
93+
TQueryC(TContracts7PackageQuery(TObjectCopiedToAnOverlappingObjectQuery()))
7794
}
7895
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Provides a library which includes a `problems` predicate for reporting....
3+
*/
4+
5+
import cpp
6+
import codingstandards.cpp.Customizations
7+
import codingstandards.cpp.Exclusions
8+
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
9+
10+
abstract class OverlappingObjectAssignmentSharedQuery extends Query { }
11+
12+
Query getQuery() { result instanceof OverlappingObjectAssignmentSharedQuery }
13+
14+
VariableAccess getAQualifier(VariableAccess va) { result = va.getQualifier+() }
15+
16+
int getAccessByteOffset(FieldAccess fa) {
17+
not fa.getQualifier() instanceof FieldAccess and result = fa.getTarget().getByteOffset()
18+
or
19+
result = fa.getTarget().getByteOffset() + getAccessByteOffset(fa.getQualifier())
20+
}
21+
22+
predicate overlaps(FieldAccess fa1, FieldAccess fa2) {
23+
exists(int startfa1, int endfa1, int startfa2, int endfa2 |
24+
startfa1 = getAccessByteOffset(fa1) and
25+
endfa1 = startfa1 + fa1.getTarget().getType().getSize() - 1 and
26+
startfa2 = getAccessByteOffset(fa2) and
27+
endfa2 = startfa2 + fa2.getTarget().getType().getSize() - 1
28+
|
29+
startfa2 >= startfa1 and endfa2 <= endfa1
30+
or
31+
startfa2 <= startfa1 and endfa2 > startfa1
32+
or
33+
startfa2 < endfa1 and endfa2 >= startfa1
34+
)
35+
}
36+
37+
query predicate problems(
38+
AssignExpr assignExpr, string message, ValueFieldAccess valuelhs, string valuelhsDesc,
39+
ValueFieldAccess valuerhs, string valuerhsDesc
40+
) {
41+
not isExcluded(assignExpr, getQuery()) and
42+
exists(Expr lhs, Expr rhs |
43+
lhs.getType() instanceof Union and
44+
rhs.getType() instanceof Union and
45+
lhs = getAQualifier(assignExpr.getLValue()) and
46+
rhs = getAQualifier(assignExpr.getRValue()) and
47+
globalValueNumber(lhs) = globalValueNumber(rhs) and
48+
valuerhs = assignExpr.getRValue() and
49+
valuelhs = assignExpr.getLValue() and // a.b.c == ((a.b).c)
50+
overlaps(valuelhs, valuerhs) and
51+
message = "An object $@ assigned to overlapping object $@." and
52+
valuelhsDesc = valuelhs.getTarget().getName() and
53+
valuerhsDesc = valuerhs.getTarget().getName()
54+
)
55+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// GENERATED FILE - DO NOT MODIFY
2+
import codingstandards.cpp.rules.overlappingobjectassignment.OverlappingObjectAssignment

cpp/autosar/test/rules/M0-2-1/test.cpp renamed to cpp/common/test/rules/overlappingobjectassignment/test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,4 @@ void internal_shift() {
5151
void separate_access() {
5252
UnionSecret_t hash1, hash2;
5353
hash2.diff.suffix = hash1.fnv.suffix; // COMPLIANT, different union.
54-
}
54+
}

rule_packages/c/Contracts7.json

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,24 @@
6666
},
6767
"queries": [
6868
{
69-
"description": "An object shall not be assigned or copied to an overlapping object.",
69+
"description": "An object shall not be assigned to an overlapping object.",
7070
"kind": "problem",
71-
"name": "An object shall not be assigned or copied to an overlapping object",
71+
"name": "An object shall not be assigned to an overlapping object",
7272
"precision": "high",
7373
"severity": "error",
74-
"short_name": "ObjectAssignedOrCopiedToAnOverlappingObject",
74+
"short_name": "ObjectAssignedToAnOverlappingObject",
75+
"shared_implementation_short_name": "OverlappingObjectAssignment",
76+
"tags": [
77+
"correctness"
78+
]
79+
},
80+
{
81+
"description": "An object shall not be copied to an overlapping object.",
82+
"kind": "problem",
83+
"name": "An object shall not be copied to an overlapping object",
84+
"precision": "high",
85+
"severity": "error",
86+
"short_name": "ObjectCopiedToAnOverlappingObject",
7587
"tags": [
7688
"correctness"
7789
]

rule_packages/cpp/Representation.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"precision": "high",
5151
"severity": "error",
5252
"short_name": "ObjectAssignedToAnOverlappingObject",
53+
"shared_implementation_short_name": "OverlappingObjectAssignment",
5354
"tags": [
5455
"correctness"
5556
]

0 commit comments

Comments
 (0)