@@ -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
245286class 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
354390import 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
357393where
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