Skip to content

Commit 57b2067

Browse files
Improve 18-1, void* casts and FPs where lowerBound appears incorrect
1 parent a5eb426 commit 57b2067

File tree

3 files changed

+17
-4
lines changed

3 files changed

+17
-4
lines changed

change_notes/2025-1-04-misra-c-technical-corrigenda-2.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
- Disallow `+` and `-` operations with an essentially char type and other types larger than int type.
55
- Note, this change affects the essential type of such expressions, which may affect other essential types rules.
66
- `RULE-18-1`, `M5-0-16` - `PointerAndDerivedPointerMustAddressSameArray.ql`, `PointerAndDerivedPointerAccessDifferentArray.ql`:
7-
- Treat casts to byte pointers as pointers to arrays of the size of the pointed-to type
7+
- Treat casts to byte pointers as pointers to arrays of the size of the pointed-to type.
88
- Fix typo in report message, "passed" replaced with "past."
9+
- Suppress results where range analysis appears potentially unreliable.
910
- `RULE-21-10`, `RULE-25-5-3`, `ENV34-C` - `CallToSetlocaleInvalidatesOldPointers.ql`, `CallToSetlocaleInvalidatesOldPointersMisra.ql`, `DoNotStorePointersReturnedByEnvFunctions.ql`:
1011
- Report usage of returned pointers from `asctime`, `ctime`, during a call to either of the former.
1112
- Report usage of returned pointers from `gmtime`, `localtime`, during a call to either of the former.

cpp/common/src/codingstandards/cpp/rules/donotusepointerarithmetictoaddressdifferentarrays/DoNotUsePointerArithmeticToAddressDifferentArrays.qll

+9-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import codingstandards.cpp.Customizations
99
import codingstandards.cpp.Exclusions
1010
import semmle.code.cpp.dataflow.new.DataFlow
1111
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
12+
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
1213
import codeql.util.Boolean
1314

1415
abstract class DoNotUsePointerArithmeticToAddressDifferentArraysSharedQuery extends Query { }
@@ -68,11 +69,13 @@ int elementSize(Type type, Boolean deref) {
6869
* length depends on `elementSize()` of the original pointed-to type.
6970
*/
7071
class CastedToBytePointer extends ArrayLikeAccess, Conversion {
72+
/** The sizeof() the pointed-to type */
7173
int size;
7274

7375
CastedToBytePointer() {
7476
getType().(PointerType).getBaseType().getSize() = 1 and
75-
size = elementSize(getExpr().getType(), true)
77+
size = elementSize(getExpr().getType(), true) and
78+
size > 1
7679
}
7780

7881
override Element getElement() { result = this }
@@ -138,7 +141,7 @@ module ArrayToArrayExprFlow = DataFlow::Global<ArrayToArrayExprConfig>;
138141

139142
/** Holds if the address taken expression `addressOf` takes the address of an array element at `index` of `array`. */
140143
predicate pointerOperandCreation(AddressOfExpr addressOf, ArrayLikeAccess array, int index) {
141-
exists(ArrayExpr ae |
144+
exists(ArrayExpr ae, Expr arrayOffset |
142145
(
143146
ArrayToArrayExprFlow::flow(array.getNode(), DataFlow::exprNode(ae.getArrayBase())) and
144147
array instanceof ArrayVariableAccess
@@ -149,7 +152,10 @@ predicate pointerOperandCreation(AddressOfExpr addressOf, ArrayLikeAccess array,
149152
// flow() may hold for `ArrayVariableAccess` in the above, even though they aren't sources
150153
array instanceof CastedToBytePointer
151154
) and
152-
index = lowerBound(ae.getArrayOffset().getFullyConverted()) and
155+
arrayOffset = ae.getArrayOffset().getFullyConverted() and
156+
index = lowerBound(arrayOffset) and
157+
// This case typically indicates range analysis has gone wrong:
158+
not index = exprMaxVal(arrayOffset) and
153159
addressOf.getOperand() = ae
154160
)
155161
}

cpp/common/test/rules/donotusepointerarithmetictoaddressdifferentarrays/test.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,10 @@ void f1() {
3939
long *p21 = (long *)&l1;
4040
void *p22 = &p21[0]; // COMPLIANT
4141
void *p23 = &p21[100]; // NON_COMPLIANT[FALSE_NEGATIVE]
42+
43+
// Void pointers have size zero and can't be analyzed.
44+
void *p24 = 0;
45+
unsigned char* p25 = (unsigned char*)p24;
46+
void *p26 = &p25[100]; // COMPLIANT
47+
4248
}

0 commit comments

Comments
 (0)