@@ -17,6 +17,9 @@ import codingstandards.cpp.misra
1717import semmle.code.cpp.dataflow.new.TaintTracking
1818import semmle.code.cpp.security.BufferAccess
1919
20+ /**
21+ * A declaration of a variable that is of an array type.
22+ */
2023class ArrayDeclaration extends VariableDeclarationEntry {
2124 int length ;
2225
@@ -28,6 +31,9 @@ class ArrayDeclaration extends VariableDeclarationEntry {
2831 int getLength ( ) { result = length }
2932}
3033
34+ /**
35+ * A call to a function that dynamically allocates memory on the heap.
36+ */
3137class HeapAllocationFunctionCall extends FunctionCall {
3238 AllocationFunction heapAllocFunction ;
3339
@@ -39,6 +45,9 @@ class HeapAllocationFunctionCall extends FunctionCall {
3945
4046 predicate isReallocCall ( ) { heapAllocFunction .getName ( ) = "realloc" }
4147
48+ /**
49+ * Get the minimum estimated number of bytes allocated.
50+ */
4251 abstract int getMinNumBytes ( ) ;
4352}
4453
@@ -62,6 +71,9 @@ class ReallocFunctionCall extends HeapAllocationFunctionCall {
6271 override int getMinNumBytes ( ) { result = lowerBound ( this .getArgument ( 1 ) ) }
6372}
6473
74+ /**
75+ * The
76+ */
6577class NarrowedHeapAllocationFunctionCall extends Cast {
6678 HeapAllocationFunctionCall alloc ;
6779
@@ -72,6 +84,15 @@ class NarrowedHeapAllocationFunctionCall extends Cast {
7284 rawResult =
7385 alloc .getMinNumBytes ( ) / this .getUnderlyingType ( ) .( PointerType ) .getBaseType ( ) .getSize ( )
7486 |
87+ /*
88+ * The `SimpleRangeAnalysis` library is not perfect, and sometimes can widen to both ends
89+ * of the type bound.
90+ *
91+ * Since it does not make sense for a object to have negative length or even zero (the
92+ * rule dictates that non-array objects should have length of 0), we clip the range and
93+ * make the minimum number of elements to 1.
94+ */
95+
7596 result = rawResult .maximum ( 1 )
7697 )
7798 }
@@ -85,6 +106,9 @@ newtype TPointerFormation =
85106 TArrayExpr ( ArrayExprBA arrayExpr ) or
86107 TPointerArithmetic ( PointerArithmeticOperation pointerArithmetic )
87108
109+ /**
110+ * Any kind of allocation of an array, either allocated on the stack or the heap.
111+ */
88112class ArrayAllocation extends TArrayAllocation {
89113 ArrayDeclaration asStackAllocation ( ) { this = TStackAllocation ( result ) }
90114
@@ -109,12 +133,19 @@ class ArrayAllocation extends TArrayAllocation {
109133 result = this .asDynamicAllocation ( ) .getLocation ( )
110134 }
111135
136+ /**
137+ * Gets the node associated with this allocation.
138+ */
112139 DataFlow:: Node getNode ( ) {
113140 result .asUninitialized ( ) = this .asStackAllocation ( ) .getVariable ( ) or
114141 result .asConvertedExpr ( ) = this .asDynamicAllocation ( )
115142 }
116143}
117144
145+ /**
146+ * Any kind of pointer formation that derives from a base pointer, either as an arithmetic operation
147+ * on pointers, or an array access expression.
148+ */
118149class PointerFormation extends TPointerFormation {
119150 ArrayExprBA asArrayExpr ( ) { this = TArrayExpr ( result ) }
120151
@@ -125,6 +156,9 @@ class PointerFormation extends TPointerFormation {
125156 result = this .asPointerArithmetic ( ) .toString ( )
126157 }
127158
159+ /**
160+ * Gets the offset of this pointer formation as calculated in relation to the base pointer.
161+ */
128162 int getOffset ( ) {
129163 result = this .asArrayExpr ( ) .getArrayOffset ( ) .getValue ( ) .toInt ( )
130164 or
@@ -137,11 +171,17 @@ class PointerFormation extends TPointerFormation {
137171 )
138172 }
139173
174+ /**
175+ * Gets the expression associated with this pointer formation.
176+ */
140177 Expr asExpr ( ) {
141178 result = this .asArrayExpr ( ) or
142- /*.getArrayBase()*/ result = this .asPointerArithmetic ( )
179+ result = this .asPointerArithmetic ( )
143180 }
144181
182+ /**
183+ * Gets the data-flow node associated with this pointer formation.
184+ */
145185 DataFlow:: Node getNode ( ) { result .asExpr ( ) = this .asExpr ( ) }
146186
147187 Location getLocation ( ) {
@@ -204,6 +244,10 @@ module Copied {
204244
205245import Copied
206246
247+ /**
248+ * A data flow configuration that starts from the allocation of an array and ends at a
249+ * pointer derived from that array.
250+ */
207251module TrackArrayConfig implements DataFlow:: ConfigSig {
208252 predicate isSource ( DataFlow:: Node node ) {
209253 exists ( ArrayAllocation arrayAllocation | node = arrayAllocation .getNode ( ) )
@@ -221,6 +265,10 @@ module TrackArrayConfig implements DataFlow::ConfigSig {
221265
222266module TrackArray = DataFlow:: Global< TrackArrayConfig > ;
223267
268+ /**
269+ * Holds if the offset of a pointer formation, as referred to by `pointerFormationNode`,
270+ * exceeds the length of the declared array, as represented by `arrayDeclarationNode`.
271+ */
224272predicate arrayIndexExceedsBounds (
225273 DataFlow:: Node arrayDeclarationNode , DataFlow:: Node pointerFormationNode , int pointerOffset ,
226274 int arrayLength
0 commit comments