Skip to content

Commit 212b266

Browse files
committed
Support the multidimensional array cases
1 parent 9493945 commit 212b266

File tree

1 file changed

+69
-35
lines changed

1 file changed

+69
-35
lines changed

cpp/misra/src/rules/RULE-8-7-1/Experimental.ql

Lines changed: 69 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ class ArrayDeclaration extends VariableDeclarationEntry {
3131
* Gets the declared length of this array.
3232
*/
3333
int getLength() { result = length }
34+
35+
int getLength(int indirection) { result = getArrayType(indirection).getArraySize() }
36+
37+
private ArrayType getArrayType(int indirection) {
38+
indirection = 0 and result = this.getType().getUnderlyingType()
39+
or
40+
exists(ArrayType at |
41+
at = getArrayType(indirection - 1) and
42+
result = at.getBaseType().getUnderlyingType()
43+
)
44+
}
3445
}
3546

3647
/**
@@ -131,9 +142,18 @@ class ArrayAllocation extends TArrayAllocation {
131142
* Gets the number of the object that the array holds. This number is exact for a stack-allocated
132143
* array, and the minimum estimated value for a heap-allocated one.
133144
*/
134-
int getLength() {
135-
result = this.asStackAllocation().getLength() or
136-
result = this.asDynamicAllocation().getMinNumElements()
145+
int getLength(DataFlow::Node node) {
146+
exists(IndirectUninitializedNode inode |
147+
inode = node and
148+
inode.getLocalVariable() = this.asStackAllocation().getVariable() and
149+
result = this.asStackAllocation().getLength(inode.getIndirection())
150+
)
151+
or
152+
result = this.asStackAllocation().getLength() and
153+
node.asUninitialized() = this.asStackAllocation().getVariable()
154+
or
155+
result = this.asDynamicAllocation().getMinNumElements() and
156+
node.asConvertedExpr() = this.asDynamicAllocation()
137157
}
138158

139159
Location getLocation() {
@@ -144,17 +164,36 @@ class ArrayAllocation extends TArrayAllocation {
144164
/**
145165
* Gets the node associated with this allocation.
146166
*/
147-
DataFlow::Node getNode() {
148-
result.asUninitialized() = this.asStackAllocation().getVariable() or
149-
result.asConvertedExpr() = this.asDynamicAllocation()
150-
}
167+
DataFlow::Node getNode() { exists(getLength(result)) }
151168

152169
Expr asExpr() {
153170
result = this.asStackAllocation().getVariable().getAnAccess() or
154171
result = this.asDynamicAllocation()
155172
}
156173
}
157174

175+
import semmle.code.cpp.ir.dataflow.internal.SsaInternals as SsaImpl
176+
177+
class IndirectUninitializedNode extends Node {
178+
LocalVariable v;
179+
int indirection;
180+
181+
IndirectUninitializedNode() {
182+
exists(SsaImpl::Definition def, SsaImpl::SourceVariable sv |
183+
def.getIndirectionIndex() = indirection and
184+
indirection > 0 and
185+
def.getValue().asInstruction() instanceof UninitializedInstruction and
186+
SsaImpl::defToNode(this, def, sv) and
187+
v = sv.getBaseVariable().(SsaImpl::BaseIRVariable).getIRVariable().getAst()
188+
)
189+
}
190+
191+
/** Gets the uninitialized local variable corresponding to this node. */
192+
LocalVariable getLocalVariable() { result = v }
193+
194+
int getIndirection() { result = indirection }
195+
}
196+
158197
/**
159198
* Any kind of pointer formation that derives from a base pointer, either as an arithmetic operation
160199
* on pointers, or an array access expression.
@@ -206,6 +245,8 @@ class PointerFormation extends TPointerFormation {
206245
)
207246
}
208247

248+
DataFlow::Node getBaseNode() { result.asIndirectExpr() = this.getBase() }
249+
209250
/**
210251
* Gets the expression associated with this pointer formation.
211252
*/
@@ -214,12 +255,12 @@ class PointerFormation extends TPointerFormation {
214255
result = this.asPointerArithmetic()
215256
}
216257

258+
private PointerAddInstruction getInstruction() { result.getAst() = this.asExpr() }
259+
217260
/**
218261
* Gets the data-flow node associated with this pointer formation.
219262
*/
220-
DataFlow::Node getNode() {
221-
result.asInstruction().(PointerAddInstruction).getAst() = this.asExpr()
222-
}
263+
DataFlow::Node getNode() { result.asInstruction() = getInstruction() }
223264

224265
Location getLocation() {
225266
result = this.asArrayExpr().getLocation() or
@@ -243,19 +284,9 @@ newtype TFatPointer =
243284
TIndexAdjusted(PointerFormation pointerFormation)
244285

245286
class FatPointer extends TFatPointer {
246-
private ArrayAllocation asAllocated() { this = TAllocated(result) }
247-
248-
private PointerFormation asIndexAdjusted() { this = TIndexAdjusted(result) }
249-
250-
predicate isAllocated() { exists(this.asAllocated()) }
287+
ArrayAllocation asAllocated() { this = TAllocated(result) }
251288

252-
predicate isIndexAdjusted() { exists(this.asIndexAdjusted()) }
253-
254-
/**
255-
* Gets the length of the underlying object, given that this fat pointer is
256-
* an *allocated pointer*.
257-
*/
258-
int getLength() { result = this.asAllocated().getLength() }
289+
PointerFormation asIndexAdjusted() { this = TIndexAdjusted(result) }
259290

260291
string toString() {
261292
result = this.asAllocated().toString() or
@@ -278,19 +309,24 @@ class FatPointer extends TFatPointer {
278309
result = this.asIndexAdjusted().getNode()
279310
}
280311

281-
Expr getBasePointer() {
282-
result = this.asAllocated().asExpr() or
283-
result = this.asIndexAdjusted().getBase()
284-
}
285-
286312
DataFlow::Node getBasePointerNode() {
313+
result = this.asIndexAdjusted().getBaseNode()
314+
or
287315
exists(PointerAddInstruction ptrAdd |
288316
result.asInstruction() = ptrAdd.getAnOperand().getDef() and
289317
(
290318
result.asInstruction().getAst() = this.asIndexAdjusted().getBase() or
291319
result.asInstruction().getAst() = this.asAllocated().asExpr()
292320
)
293321
)
322+
or
323+
exists(PointerSubInstruction ptrSub |
324+
result.asInstruction() = ptrSub.getAnOperand().getDef() and
325+
(
326+
result.asInstruction().getAst() = this.asIndexAdjusted().getBase() or
327+
result.asInstruction().getAst() = this.asAllocated().asExpr()
328+
)
329+
)
294330
}
295331
}
296332

@@ -327,7 +363,7 @@ predicate srcSinkLengthMap(
327363
sinkOffset = end.getOffset() and
328364
(
329365
/* Base case: The object is allocated and a fat pointer created. */
330-
length = start.getLength()
366+
length = start.asAllocated().getLength(src.getNode())
331367
or
332368
/* Recursive case: A fat pointer is derived from a fat pointer. */
333369
srcSinkLengthMap(_, start, _, srcOffset, length)
@@ -353,21 +389,19 @@ module TrackArray = DataFlow::Global<TrackArrayConfig>;
353389

354390
import TrackArray::PathGraph
355391

356-
from TrackArray::PathNode src, TrackArray::PathNode sink, string message
392+
from TrackArray::PathNode src, TrackArray::PathNode sink, FatPointer end, string message
357393
where
358394
not isExcluded(sink.getNode().asExpr(),
359395
Memory1Package::pointerArithmeticFormsAnInvalidPointerQuery()) and
360-
exists(FatPointer start, FatPointer end, int srcOffset, int sinkOffset, int length |
396+
exists(FatPointer start, int srcOffset, int sinkOffset, int length |
361397
src.getNode() = start.getNode() and
362-
sink.getNode().asExpr() = end.getBasePointer()
398+
sink.getNode() = end.getBasePointerNode()
363399
|
364400
srcSinkLengthMap(start, end, srcOffset, sinkOffset, length) and
365401
(
366402
srcOffset + sinkOffset < 0 or // Underflow detection
367403
srcOffset + sinkOffset > length // Overflow detection
368404
) and
369-
message =
370-
"start: " + start + ", end: " + end + "srcOffset: " + srcOffset + ", sinkOffset: " +
371-
sinkOffset + ", length: " + length
405+
message = "srcOffset: " + srcOffset + ", sinkOffset: " + sinkOffset + ", length: " + length
372406
)
373-
select sink, src, sink, message
407+
select end, src, sink, message

0 commit comments

Comments
 (0)