Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 31d093a

Browse filesBrowse files
authored
Merge branch 'main' into jsinglet/bump2
2 parents 1c60e58 + e451f27 commit 31d093a
Copy full SHA for 31d093a

File tree

141 files changed

+4287
-112
lines changed
Filter options

Some content is hidden

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

141 files changed

+4287
-112
lines changed

‎.vscode/tasks.json

Copy file name to clipboardExpand all lines: .vscode/tasks.json
+2-3Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,11 @@
185185
"type": "pickString",
186186
"options": [
187187
"Allocations",
188-
"Banned",
189188
"BannedFunctions",
189+
"BannedLibraries",
190190
"BannedSyntax",
191191
"BannedTypes",
192192
"Classes",
193-
"Classes",
194-
"Classes",
195193
"Comments",
196194
"Contracts1",
197195
"Concurrency",
@@ -212,6 +210,7 @@
212210
"IO1",
213211
"IO2",
214212
"IO3",
213+
"IO4",
215214
"Includes",
216215
"Initialization",
217216
"IntegerConversion",
+192Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# ARR39-C: Do not add or subtract a scaled integer to a pointer
2+
3+
This query implements the CERT-C rule ARR39-C:
4+
5+
> Do not add or subtract a scaled integer to a pointer
6+
7+
8+
## Description
9+
10+
Pointer arithmetic is appropriate only when the pointer argument refers to an array (see [ARR37-C. Do not add or subtract an integer to a pointer to a non-array object](https://wiki.sei.cmu.edu/confluence/display/c/ARR37-C.+Do+not+add+or+subtract+an+integer+to+a+pointer+to+a+non-array+object)), including an array of bytes. When performing pointer arithmetic, the size of the value to add to or subtract from a pointer is automatically scaled to the size of the type of the referenced array object. Adding or subtracting a scaled integer value to or from a pointer is invalid because it may yield a pointer that does not point to an element within or one past the end of the array. (See [ARR30-C. Do not form or use out-of-bounds pointers or array subscripts](https://wiki.sei.cmu.edu/confluence/display/c/ARR30-C.+Do+not+form+or+use+out-of-bounds+pointers+or+array+subscripts).)
11+
12+
Adding a pointer to an array of a type other than character to the result of the `sizeof` operator or `offsetof` macro, which returns a size and an offset, respectively, violates this rule. However, adding an array pointer to the number of array elements, for example, by using the `arr[sizeof(arr)/sizeof(arr[0])])` idiom, is allowed provided that `arr` refers to an array and not a pointer.
13+
14+
## Noncompliant Code Example
15+
16+
In this noncompliant code example, `sizeof(buf)` is added to the array `buf`. This example is noncompliant because `sizeof(buf)` is scaled by `int` and then scaled again when added to `buf`.
17+
18+
```cpp
19+
enum { INTBUFSIZE = 80 };
20+
21+
extern int getdata(void);
22+
int buf[INTBUFSIZE];
23+
24+
void func(void) {
25+
int *buf_ptr = buf;
26+
27+
while (buf_ptr < (buf + sizeof(buf))) {
28+
*buf_ptr++ = getdata();
29+
}
30+
}
31+
```
32+
33+
## Compliant Solution
34+
35+
This compliant solution uses an unscaled integer to obtain a pointer to the end of the array:
36+
37+
```cpp
38+
enum { INTBUFSIZE = 80 };
39+
40+
extern int getdata(void);
41+
int buf[INTBUFSIZE];
42+
43+
void func(void) {
44+
int *buf_ptr = buf;
45+
46+
while (buf_ptr < (buf + INTBUFSIZE)) {
47+
*buf_ptr++ = getdata();
48+
}
49+
}
50+
```
51+
52+
## Noncompliant Code Example
53+
54+
In this noncompliant code example, `skip` is added to the pointer `s`. However, `skip` represents the byte offset of `ull_b` in `struct big`. When added to `s`, `skip` is scaled by the size of `struct big`.
55+
56+
```cpp
57+
#include <string.h>
58+
#include <stdlib.h>
59+
#include <stddef.h>
60+
61+
struct big {
62+
unsigned long long ull_a;
63+
unsigned long long ull_b;
64+
unsigned long long ull_c;
65+
int si_e;
66+
int si_f;
67+
};
68+
69+
void func(void) {
70+
size_t skip = offsetof(struct big, ull_b);
71+
struct big *s = (struct big *)malloc(sizeof(struct big));
72+
if (s == NULL) {
73+
/* Handle malloc() error */
74+
}
75+
76+
memset(s + skip, 0, sizeof(struct big) - skip);
77+
/* ... */
78+
free(s);
79+
s = NULL;
80+
}
81+
```
82+
83+
## Compliant Solution
84+
85+
This compliant solution uses an `unsigned char *` to calculate the offset instead of using a `struct big *`, which would result in scaled arithmetic:
86+
87+
```cpp
88+
#include <string.h>
89+
#include <stdlib.h>
90+
#include <stddef.h>
91+
92+
struct big {
93+
unsigned long long ull_a;
94+
unsigned long long ull_b;
95+
unsigned long long ull_c;
96+
int si_d;
97+
int si_e;
98+
};
99+
100+
void func(void) {
101+
size_t skip = offsetof(struct big, ull_b);
102+
unsigned char *ptr = (unsigned char *)malloc(
103+
sizeof(struct big)
104+
);
105+
if (ptr == NULL) {
106+
/* Handle malloc() error */
107+
}
108+
109+
memset(ptr + skip, 0, sizeof(struct big) - skip);
110+
/* ... */
111+
free(ptr);
112+
ptr = NULL;
113+
}
114+
```
115+
116+
## Noncompliant Code Example
117+
118+
In this noncompliant code example, `wcslen(error_msg) * sizeof(wchar_t)` bytes are scaled by the size of `wchar_t` when added to `error_msg`:
119+
120+
```cpp
121+
#include <wchar.h>
122+
#include <stdio.h>
123+
124+
enum { WCHAR_BUF = 128 };
125+
126+
void func(void) {
127+
wchar_t error_msg[WCHAR_BUF];
128+
129+
wcscpy(error_msg, L"Error: ");
130+
fgetws(error_msg + wcslen(error_msg) * sizeof(wchar_t),
131+
WCHAR_BUF - 7, stdin);
132+
/* ... */
133+
}
134+
```
135+
136+
## Compliant Solution
137+
138+
This compliant solution does not scale the length of the string; `wcslen()` returns the number of characters and the addition to `error_msg` is scaled:
139+
140+
```cpp
141+
#include <wchar.h>
142+
#include <stdio.h>
143+
144+
enum { WCHAR_BUF = 128 };
145+
const wchar_t ERROR_PREFIX[7] = L"Error: ";
146+
147+
void func(void) {
148+
const size_t prefix_len = wcslen(ERROR_PREFIX);
149+
wchar_t error_msg[WCHAR_BUF];
150+
151+
wcscpy(error_msg, ERROR_PREFIX);
152+
fgetws(error_msg + prefix_len,
153+
WCHAR_BUF - prefix_len, stdin);
154+
/* ... */
155+
}
156+
```
157+
158+
## Risk Assessment
159+
160+
Failure to understand and properly use pointer arithmetic can allow an attacker to execute arbitrary code.
161+
162+
<table> <tbody> <tr> <th> Rule </th> <th> Severity </th> <th> Likelihood </th> <th> Remediation Cost </th> <th> Priority </th> <th> Level </th> </tr> <tr> <td> ARR39-C </td> <td> High </td> <td> Probable </td> <td> High </td> <td> <strong>P6</strong> </td> <td> <strong>L2</strong> </td> </tr> </tbody> </table>
163+
164+
165+
## Automated Detection
166+
167+
<table> <tbody> <tr> <th> Tool </th> <th> Version </th> <th> Checker </th> <th> Description </th> </tr> <tr> <td> <a> Astrée </a> </td> <td> 22.04 </td> <td> <strong>scaled-pointer-arithmetic </strong> </td> <td> Partially checked Besides direct rule violations, Astrée reports all (resulting) out-of-bound array accesses. </td> </tr> <tr> <td> <a> Axivion Bauhaus Suite </a> </td> <td> 7.2.0 </td> <td> <strong>CertC-ARR39</strong> </td> <td> Fully implemented </td> </tr> <tr> <td> <a> CodeSonar </a> </td> <td> 7.0p0 </td> <td> <strong>LANG.MEM.BO</strong> <strong>LANG.MEM.BU</strong> <strong>LANG.MEM.TBA</strong> <strong>LANG.MEM.TO</strong> <strong>LANG.MEM.TULANG.STRUCT.PARITH</strong> <strong>LANG.STRUCT.PBB</strong> <strong>LANG.STRUCT.PPE</strong> <strong>BADFUNC.BO.\*</strong> </td> <td> Buffer overrun Buffer underrun Tainted buffer access Type overrun Type underrun Pointer Arithmetic Pointer before beginning of object Pointer past end of object A collection of warning classes that report uses of library functions prone to internal buffer overflows. </td> </tr> <tr> <td> <a> Coverity </a> </td> <td> 2017.07 </td> <td> <strong>BAD_SIZEOF</strong> </td> <td> Partially implemented </td> </tr> <tr> <td> <a> Helix QAC </a> </td> <td> 2022.2 </td> <td> <strong>C4955, C4956, C4957</strong> <strong>C++4955, C++4956, C++4957</strong> </td> <td> </td> </tr> <tr> <td> <a> Klocwork </a> </td> <td> 2022.2 </td> <td> <strong>MISRA.PTR.ARITH.2012</strong> </td> <td> </td> </tr> <tr> <td> <a> LDRA tool suite </a> </td> <td> 9.7.1 </td> <td> <strong>47 S, 489 S, 567 S,64 X, 66 X, 68 X,69 X, 70 X, 71 X</strong> </td> <td> Partially implemented </td> </tr> <tr> <td> <a> Parasoft C/C++test </a> </td> <td> 2022.1 </td> <td> <strong>CERT_C-ARR39-a</strong> <strong>CERT_C-ARR39-b</strong> <strong>CERT_C-ARR39-c</strong> </td> <td> Avoid accessing arrays out of bounds Pointer arithmetic should not be used Do not add or subtract a scaled integer to a pointer </td> </tr> <tr> <td> Polyspace Bug Finder </td> <td> R2022a </td> <td> <a> CERT C: Rule ARR39-C </a> </td> <td> Checks for: Incorrect pointer scalingncorrect pointer scaling, pointer access out of boundsointer access out of bounds, possible misuse of sizeofossible misuse of sizeof. Rule partially covered. </td> </tr> <tr> <td> <a> PRQA QA-C </a> </td> <td> 9.7 </td> <td> <strong> 4955, 4956, 4957</strong> </td> <td> </td> </tr> <tr> <td> <a> PRQA QA-C++ </a> </td> <td> 4.4 </td> <td> <strong>4955, 4956, 4957</strong> </td> <td> </td> </tr> <tr> <td> <a> RuleChecker </a> </td> <td> 22.04 </td> <td> <strong>scaled-pointer-arithmetic</strong> </td> <td> Partially checked </td> </tr> <tr> <td> <a> TrustInSoft Analyzer </a> </td> <td> 1.38 </td> <td> <strong>index_in_address</strong> </td> <td> Exhaustively detects undefined behavior (see <a> one compliant and one non-compliant example </a> ). </td> </tr> </tbody> </table>
168+
169+
170+
## Related Vulnerabilities
171+
172+
Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the [CERT website](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+EXP41-C).
173+
174+
## Related Guidelines
175+
176+
[Key here](https://wiki.sei.cmu.edu/confluence/display/c/How+this+Coding+Standard+is+Organized#HowthisCodingStandardisOrganized-RelatedGuidelines) (explains table format and definitions)
177+
178+
<table> <tbody> <tr> <th> Taxonomy </th> <th> Taxonomy item </th> <th> Relationship </th> </tr> <tr> <td> <a> CERT C Secure Coding Standard </a> </td> <td> <a> ARR30-C. Do not form or use out-of-bounds pointers or array subscripts </a> </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> CERT C Secure Coding Standard </a> </td> <td> <a> ARR37-C. Do not add or subtract an integer to a pointer to a non-array object </a> </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> ISO/IEC TR 24772:2013 </a> </td> <td> Pointer Casting and Pointer Type Changes \[HFC\] </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> ISO/IEC TR 24772:2013 </a> </td> <td> Pointer Arithmetic \[RVG\] </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> MISRA C:2012 </a> </td> <td> Rule 18.1 (required) </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> MISRA C:2012 </a> </td> <td> Rule 18.2 (required) </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> MISRA C:2012 </a> </td> <td> Rule 18.3 (required) </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> MISRA C:2012 </a> </td> <td> Rule 18.4 (advisory) </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> CWE 2.11 </a> </td> <td> <a> CWE-468 </a> , Incorrect Pointer Scaling </td> <td> 2017-07-07: CERT: Exact </td> </tr> </tbody> </table>
179+
180+
181+
## Bibliography
182+
183+
<table> <tbody> <tr> <td> \[ <a> Dowd 2006 </a> \] </td> <td> Chapter 6, "C Language Issues" </td> </tr> <tr> <td> \[ <a> Murenin 07 </a> \] </td> <td> </td> </tr> </tbody> </table>
184+
185+
186+
## Implementation notes
187+
188+
None
189+
190+
## References
191+
192+
* CERT-C: [ARR39-C: Do not add or subtract a scaled integer to a pointer](https://wiki.sei.cmu.edu/confluence/display/c)
+131Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/**
2+
* @id c/cert/do-not-add-or-subtract-a-scaled-integer-to-a-pointer
3+
* @name ARR39-C: Do not add or subtract a scaled integer to a pointer
4+
* @description Adding or subtracting a scaled integer value to or from a pointer may yield an
5+
* out-of-bounds pointer.
6+
* @kind path-problem
7+
* @precision high
8+
* @problem.severity error
9+
* @tags external/cert/id/arr39-c
10+
* correctness
11+
* external/cert/obligation/rule
12+
*/
13+
14+
import cpp
15+
import codingstandards.c.cert
16+
import semmle.code.cpp.dataflow.TaintTracking
17+
import DataFlow::PathGraph
18+
19+
/**
20+
* An expression which performs pointer arithmetic
21+
*/
22+
abstract class PointerArithmeticExpr extends Expr {
23+
abstract Expr getPointer();
24+
25+
abstract Expr getOperand();
26+
}
27+
28+
/**
29+
* A pointer arithmetic binary operation expression.
30+
*/
31+
class SimplePointerArithmeticExpr extends PointerArithmeticExpr, PointerArithmeticOperation {
32+
override Expr getPointer() { result = this.getLeftOperand() }
33+
34+
override Expr getOperand() { result = this.getRightOperand() }
35+
}
36+
37+
/**
38+
* A pointer arithmetic assignment expression.
39+
*/
40+
class AssignPointerArithmeticExpr extends PointerArithmeticExpr, AssignOperation {
41+
AssignPointerArithmeticExpr() {
42+
this instanceof AssignPointerAddExpr or
43+
this instanceof AssignPointerSubExpr
44+
}
45+
46+
override Expr getPointer() { result = this.getLValue() }
47+
48+
override Expr getOperand() { result = this.getRValue() }
49+
}
50+
51+
/**
52+
* A pointer arithmetic array access expression.
53+
*/
54+
class ArrayPointerArithmeticExpr extends PointerArithmeticExpr, ArrayExpr {
55+
override Expr getPointer() { result = this.getArrayBase() }
56+
57+
override Expr getOperand() { result = this.getArrayOffset() }
58+
}
59+
60+
/**
61+
* An expression which invokes the `offsetof` macro or `__builtin_offsetof` operation.
62+
*/
63+
class OffsetOfExpr extends Expr {
64+
OffsetOfExpr() {
65+
this instanceof BuiltInOperationBuiltInOffsetOf
66+
or
67+
exists(MacroInvocation mi | mi.getMacroName() = "offsetof" and mi.getExpr() = this)
68+
}
69+
}
70+
71+
/**
72+
* An array expression conforming to the `arr[sizeof(arr)/sizeof(arr[0])]` idiom.
73+
*/
74+
class ArrayCountOfExpr extends ArrayExpr {
75+
ArrayCountOfExpr() {
76+
exists(DivExpr div, Variable arr, VariableAccess left, ArrayExpr right |
77+
div = this.getArrayOffset() and
78+
arr = this.getArrayBase().(VariableAccess).getTarget() and
79+
// exclude cases where arr is a pointer rather than an array
80+
arr.getUnderlyingType() instanceof ArrayType and
81+
// holds if the dividend is sizeof(arr)
82+
left = div.getLeftOperand().(SizeofExprOperator).getExprOperand() and
83+
left.getTarget() = this.getArrayBase().(VariableAccess).getTarget() and
84+
// holds if the divisor is sizeof(arr[0])
85+
right = div.getRightOperand().(SizeofExprOperator).getExprOperand() and
86+
right.getArrayBase().(VariableAccess).getTarget() = arr and
87+
right.getArrayOffset().(Literal).getValue() = "0"
88+
)
89+
}
90+
}
91+
92+
/**
93+
* An `offsetof` expression or a `sizeof` expression with an operand of a size greater than 1.
94+
*/
95+
class ScaledIntegerExpr extends Expr {
96+
ScaledIntegerExpr() {
97+
not this.getParent*() instanceof ArrayCountOfExpr and
98+
(
99+
this.(SizeofExprOperator).getExprOperand().getType().getSize() > 1
100+
or
101+
this.(SizeofTypeOperator).getTypeOperand().getSize() > 1
102+
or
103+
this instanceof OffsetOfExpr
104+
)
105+
}
106+
}
107+
108+
/**
109+
* A data-flow configuration modeling data-flow from a `ScaledIntegerExpr` to a
110+
* `PointerArithmeticExpr` where the pointer does not point to a 1-byte type.
111+
*/
112+
class ScaledIntegerPointerArithmeticConfig extends DataFlow::Configuration {
113+
ScaledIntegerPointerArithmeticConfig() { this = "ScaledIntegerPointerArithmeticConfig" }
114+
115+
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ScaledIntegerExpr }
116+
117+
override predicate isSink(DataFlow::Node sink) {
118+
exists(PointerArithmeticExpr pa |
119+
// exclude pointers to 1-byte types as they do not scale
120+
pa.getPointer().getFullyConverted().getType().(DerivedType).getBaseType().getSize() != 1 and
121+
pa.getOperand().getAChild*() = sink.asExpr()
122+
)
123+
}
124+
}
125+
126+
from ScaledIntegerPointerArithmeticConfig config, DataFlow::PathNode src, DataFlow::PathNode sink
127+
where
128+
not isExcluded(sink.getNode().asExpr(),
129+
Pointers2Package::doNotAddOrSubtractAScaledIntegerToAPointerQuery()) and
130+
config.hasFlowPath(src, sink)
131+
select sink, src, sink, "Scaled integer used in pointer arithmetic."

‎c/cert/src/rules/ENV33-C/DoNotCallSystem.ql

Copy file name to clipboardExpand all lines: c/cert/src/rules/ENV33-C/DoNotCallSystem.ql
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* @problem.severity error
88
* @tags external/cert/id/env33-c
99
* security
10-
* external/cert/obligtion/rule
10+
* external/cert/obligation/rule
1111
*/
1212

1313
import cpp

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.