Skip to content

Commit fee555c

Browse files
committed
RULE-19-1 support and test for memcpy unions
1 parent ab43602 commit fee555c

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

c/misra/src/rules/RULE-19-1/ObjectCopiedToAnOverlappingObject.ql

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ import codingstandards.c.misra
1515
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
1616
import semmle.code.cpp.dataflow.DataFlow
1717

18+
/**
19+
* Offset in bytes of a field access
20+
*/
21+
int getAccessByteOffset(FieldAccess fa) {
22+
not fa.getQualifier() instanceof FieldAccess and result = fa.getTarget().getByteOffset()
23+
or
24+
result = fa.getTarget().getByteOffset() + getAccessByteOffset(fa.getQualifier())
25+
}
26+
1827
/**
1928
* Models calls to memcpy on overlapping objects
2029
*/
@@ -40,15 +49,17 @@ class MemcpyCall extends Locatable {
4049
result =
4150
[
4251
e.(VariableAccess), e.(PointerAddExpr).getLeftOperand(),
43-
e.(AddressOfExpr).getOperand().(ArrayExpr).getArrayBase()
52+
e.(AddressOfExpr).getOperand().(ArrayExpr).getArrayBase+(),
53+
e.(AddressOfExpr).getOperand().(ValueFieldAccess).getQualifier+()
4454
]
4555
}
4656

4757
int getOffset(Expr e) {
4858
result =
4959
[
5060
e.(PointerAddExpr).getRightOperand().getValue().toInt(),
51-
e.(AddressOfExpr).getOperand().(ArrayExpr).getArrayOffset().getValue().toInt()
61+
e.(AddressOfExpr).getOperand().(ArrayExpr).getArrayOffset().getValue().toInt(),
62+
getAccessByteOffset(e.(AddressOfExpr).getOperand()),
5263
]
5364
or
5465
e instanceof VariableAccess and result = 0

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
| 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 |
33
| 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 |
44
| 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 |
5+
| test.c:52:3:52:8 | call to memcpy | The object to copy $@ overlaps the object to copy $@. | test.c:52:21:52:26 | & ... | from | test.c:52:10:52:18 | & ... | to |

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,35 @@ void g(void) {
2020
// Exception 2
2121
memmove(&o[1], &o[0], 2u * sizeof(o[0])); // COMPLIANT
2222
}
23+
24+
struct s1 {
25+
int m1[10];
26+
};
27+
struct s2 {
28+
int m1;
29+
struct s1 m2;
30+
};
31+
union u {
32+
struct s1 m1;
33+
struct s2 m2;
34+
} u1;
35+
36+
typedef struct {
37+
char buf[8];
38+
} Union_t;
39+
union {
40+
unsigned char uc[24];
41+
struct {
42+
Union_t prefix;
43+
Union_t suffix;
44+
} fnv;
45+
struct {
46+
unsigned char padding[16];
47+
Union_t suffix;
48+
} diff;
49+
} u2;
50+
51+
void test_unions() {
52+
memcpy(&u1.m2.m2, &u1.m1, sizeof(u1.m1)); // NON_COMPLIANT
53+
memcpy(&u2.diff.suffix, &u2.fnv.suffix, sizeof(u2.fnv.suffix)); // COMPLIANT
54+
}

0 commit comments

Comments
 (0)