@@ -6,56 +6,71 @@ private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
66private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
77private import semmle.code.cpp.ir.internal.IntegerInterval as Interval
88private import semmle.code.cpp.ir.implementation.internal.OperandTag
9+ private import AliasConfiguration
910
1011private class IntValue = Ints:: IntValue ;
1112
13+ private predicate isIndirectOrBufferMemoryAccess ( MemoryAccessKind kind ) {
14+ kind instanceof IndirectMemoryAccess or
15+ kind instanceof BufferMemoryAccess
16+ }
17+
1218private predicate hasResultMemoryAccess (
13- Instruction instr , IRVariable var , IRType type , Language:: LanguageType languageType ,
19+ Instruction instr , Allocation var , IRType type , Language:: LanguageType languageType ,
1420 IntValue startBitOffset , IntValue endBitOffset , boolean isMayAccess
1521) {
16- resultPointsTo ( instr .getResultAddress ( ) , var , startBitOffset ) and
17- languageType = instr .getResultLanguageType ( ) and
18- type = languageType .getIRType ( ) and
19- ( if instr .hasResultMayMemoryAccess ( ) then isMayAccess = true else isMayAccess = false ) and
20- if exists ( type .getByteSize ( ) )
21- then endBitOffset = Ints:: add ( startBitOffset , Ints:: mul ( type .getByteSize ( ) , 8 ) )
22- else endBitOffset = Ints:: unknown ( )
22+ exists ( AddressOperand addrOperand |
23+ addrOperand = instr .getResultAddressOperand ( ) and
24+ addressOperandAllocationAndOffset ( addrOperand , var , startBitOffset ) and
25+ languageType = instr .getResultLanguageType ( ) and
26+ type = languageType .getIRType ( ) and
27+ isIndirectOrBufferMemoryAccess ( instr .getResultMemoryAccess ( ) ) and
28+ ( if instr .hasResultMayMemoryAccess ( ) then isMayAccess = true else isMayAccess = false ) and
29+ if exists ( type .getByteSize ( ) )
30+ then endBitOffset = Ints:: add ( startBitOffset , Ints:: mul ( type .getByteSize ( ) , 8 ) )
31+ else endBitOffset = Ints:: unknown ( )
32+ )
2333}
2434
2535private predicate hasOperandMemoryAccess (
26- MemoryOperand operand , IRVariable var , IRType type , Language:: LanguageType languageType ,
36+ MemoryOperand operand , Allocation var , IRType type , Language:: LanguageType languageType ,
2737 IntValue startBitOffset , IntValue endBitOffset , boolean isMayAccess
2838) {
29- resultPointsTo ( operand .getAddressOperand ( ) .getAnyDef ( ) , var , startBitOffset ) and
30- languageType = operand .getLanguageType ( ) and
31- type = languageType .getIRType ( ) and
32- ( if operand .hasMayReadMemoryAccess ( ) then isMayAccess = true else isMayAccess = false ) and
33- if exists ( type .getByteSize ( ) )
34- then endBitOffset = Ints:: add ( startBitOffset , Ints:: mul ( type .getByteSize ( ) , 8 ) )
35- else endBitOffset = Ints:: unknown ( )
39+ exists ( AddressOperand addrOperand |
40+ addrOperand = operand .getAddressOperand ( ) and
41+ addressOperandAllocationAndOffset ( addrOperand , var , startBitOffset ) and
42+ languageType = operand .getLanguageType ( ) and
43+ type = languageType .getIRType ( ) and
44+ isIndirectOrBufferMemoryAccess ( operand .getMemoryAccess ( ) ) and
45+ ( if operand .hasMayReadMemoryAccess ( ) then isMayAccess = true else isMayAccess = false ) and
46+ if exists ( type .getByteSize ( ) )
47+ then endBitOffset = Ints:: add ( startBitOffset , Ints:: mul ( type .getByteSize ( ) , 8 ) )
48+ else endBitOffset = Ints:: unknown ( )
49+ )
3650}
3751
3852private newtype TMemoryLocation =
3953 TVariableMemoryLocation (
40- IRVariable var , IRType type , Language:: LanguageType languageType , IntValue startBitOffset ,
54+ Allocation var , IRType type , Language:: LanguageType languageType , IntValue startBitOffset ,
4155 IntValue endBitOffset , boolean isMayAccess
4256 ) {
4357 (
4458 hasResultMemoryAccess ( _, var , type , _, startBitOffset , endBitOffset , isMayAccess )
4559 or
4660 hasOperandMemoryAccess ( _, var , type , _, startBitOffset , endBitOffset , isMayAccess )
4761 or
48- exists ( IRAutomaticVariable autoVar |
49- // Always create a memory location for the entire variable.
50- autoVar = var and
51- type = autoVar .getIRType ( ) and
52- startBitOffset = 0 and
53- endBitOffset = type .getByteSize ( ) * 8 and
54- isMayAccess = false
55- )
62+ // For a stack variable, always create a memory location for the entire variable.
63+ var .isAlwaysAllocatedOnStack ( ) and
64+ type = var .getIRType ( ) and
65+ startBitOffset = 0 and
66+ endBitOffset = type .getByteSize ( ) * 8 and
67+ isMayAccess = false
5668 ) and
5769 languageType = type .getCanonicalLanguageType ( )
5870 } or
71+ TEntireAllocationMemoryLocation ( IndirectParameterAllocation var , boolean isMayAccess ) {
72+ isMayAccess = false or isMayAccess = true
73+ } or
5974 TUnknownMemoryLocation ( IRFunction irFunc , boolean isMayAccess ) {
6075 isMayAccess = false or isMayAccess = true
6176 } or
@@ -94,6 +109,8 @@ abstract class MemoryLocation extends TMemoryLocation {
94109
95110 abstract predicate isMayAccess ( ) ;
96111
112+ Allocation getAllocation ( ) { none ( ) }
113+
97114 /**
98115 * Holds if the location cannot be overwritten except by definition of a `MemoryLocation` for
99116 * which `def.canDefineReadOnly()` holds.
@@ -114,26 +131,63 @@ abstract class MemoryLocation extends TMemoryLocation {
114131
115132abstract class VirtualVariable extends MemoryLocation { }
116133
134+ abstract class AllocationMemoryLocation extends MemoryLocation {
135+ Allocation var ;
136+ boolean isMayAccess ;
137+
138+ AllocationMemoryLocation ( ) {
139+ this instanceof TMemoryLocation and
140+ isMayAccess = false
141+ or
142+ isMayAccess = true // Just ensures that `isMayAccess` is bound.
143+ }
144+
145+ final override VirtualVariable getVirtualVariable ( ) {
146+ if allocationEscapes ( var )
147+ then result = TAllAliasedMemory ( var .getEnclosingIRFunction ( ) , false )
148+ else result .( AllocationMemoryLocation ) .getAllocation ( ) = var
149+ }
150+
151+ final override IRFunction getIRFunction ( ) { result = var .getEnclosingIRFunction ( ) }
152+
153+ final override Location getLocation ( ) { result = var .getLocation ( ) }
154+
155+ final override Allocation getAllocation ( ) { result = var }
156+
157+ final override predicate isMayAccess ( ) { isMayAccess = true }
158+
159+ final override predicate isReadOnly ( ) { var .isReadOnly ( ) }
160+ }
161+
117162/**
118163 * An access to memory within a single known `IRVariable`. The variable may be either an unescaped variable
119164 * (with its own `VirtualIRVariable`) or an escaped variable (assigned to `UnknownVirtualVariable`).
120165 */
121- class VariableMemoryLocation extends TVariableMemoryLocation , MemoryLocation {
122- IRVariable var ;
166+ class VariableMemoryLocation extends TVariableMemoryLocation , AllocationMemoryLocation {
123167 IRType type ;
124168 Language:: LanguageType languageType ;
125169 IntValue startBitOffset ;
126170 IntValue endBitOffset ;
127- boolean isMayAccess ;
128171
129172 VariableMemoryLocation ( ) {
130173 this = TVariableMemoryLocation ( var , type , languageType , startBitOffset , endBitOffset ,
131174 isMayAccess )
132175 }
133176
177+ private string getIntervalString ( ) {
178+ if coversEntireVariable ( )
179+ then result = ""
180+ else result = Interval:: getIntervalString ( startBitOffset , endBitOffset )
181+ }
182+
183+ private string getTypeString ( ) {
184+ if coversEntireVariable ( ) and type = var .getIRType ( )
185+ then result = ""
186+ else result = "<" + languageType .toString ( ) + ">"
187+ }
188+
134189 final override string toStringInternal ( ) {
135- result = var .toString ( ) + Interval:: getIntervalString ( startBitOffset , endBitOffset ) + "<" +
136- type .toString ( ) + ", " + languageType .toString ( ) + ">"
190+ result = var .toString ( ) + getIntervalString ( ) + getTypeString ( )
137191 }
138192
139193 final override Language:: LanguageType getType ( ) {
@@ -151,34 +205,16 @@ class VariableMemoryLocation extends TVariableMemoryLocation, MemoryLocation {
151205 result = type .getCanonicalLanguageType ( )
152206 }
153207
154- final override IRFunction getIRFunction ( ) { result = var .getEnclosingIRFunction ( ) }
155-
156- final override Location getLocation ( ) { result = var .getLocation ( ) }
157-
158208 final IntValue getStartBitOffset ( ) { result = startBitOffset }
159209
160210 final IntValue getEndBitOffset ( ) { result = endBitOffset }
161211
162- final IRVariable getVariable ( ) { result = var }
163-
164212 final override string getUniqueId ( ) {
165213 result = var .getUniqueId ( ) + Interval:: getIntervalString ( startBitOffset , endBitOffset ) + "<" +
166214 type .getIdentityString ( ) + ">"
167215 }
168216
169- final override VirtualVariable getVirtualVariable ( ) {
170- if variableAddressEscapes ( var )
171- then result = TAllAliasedMemory ( var .getEnclosingIRFunction ( ) , false )
172- else
173- result = TVariableMemoryLocation ( var , var .getIRType ( ) , _, 0 ,
174- var .getIRType ( ) .getByteSize ( ) * 8 , false )
175- }
176-
177- final override predicate isMayAccess ( ) { isMayAccess = true }
178-
179- final override predicate isReadOnly ( ) { var .isReadOnly ( ) }
180-
181- final override predicate isAlwaysAllocatedOnStack ( ) { var instanceof IRAutomaticVariable }
217+ final override predicate isAlwaysAllocatedOnStack ( ) { var .isAlwaysAllocatedOnStack ( ) }
182218
183219 /**
184220 * Holds if this memory location covers the entire variable.
@@ -189,14 +225,34 @@ class VariableMemoryLocation extends TVariableMemoryLocation, MemoryLocation {
189225 }
190226}
191227
228+ class EntireAllocationMemoryLocation extends TEntireAllocationMemoryLocation ,
229+ AllocationMemoryLocation {
230+ EntireAllocationMemoryLocation ( ) { this = TEntireAllocationMemoryLocation ( var , isMayAccess ) }
231+
232+ final override string toStringInternal ( ) { result = var .toString ( ) }
233+
234+ final override Language:: LanguageType getType ( ) {
235+ result = any ( IRUnknownType unknownType ) .getCanonicalLanguageType ( )
236+ }
237+
238+ final override string getUniqueId ( ) { result = var .getUniqueId ( ) }
239+ }
240+
241+ class EntireAllocationVirtualVariable extends EntireAllocationMemoryLocation , VirtualVariable {
242+ EntireAllocationVirtualVariable ( ) {
243+ not allocationEscapes ( var ) and
244+ not isMayAccess ( )
245+ }
246+ }
247+
192248/**
193249 * Represents the `MemoryLocation` for an `IRVariable` that acts as its own `VirtualVariable`. Includes any
194250 * `VariableMemoryLocation` that exactly overlaps its entire `IRVariable`, and only if that `IRVariable` does not
195251 * escape.
196252 */
197253class VariableVirtualVariable extends VariableMemoryLocation , VirtualVariable {
198254 VariableVirtualVariable ( ) {
199- not variableAddressEscapes ( var ) and
255+ not allocationEscapes ( var ) and
200256 type = var .getIRType ( ) and
201257 coversEntireVariable ( ) and
202258 not isMayAccess ( )
@@ -354,13 +410,30 @@ private Overlap getExtentOverlap(MemoryLocation def, MemoryLocation use) {
354410 not use .isAlwaysAllocatedOnStack ( )
355411 )
356412 or
413+ def .getVirtualVariable ( ) = use .getVirtualVariable ( ) and
414+ def instanceof EntireAllocationMemoryLocation and
415+ (
416+ // EntireAllocationMemoryLocation exactly overlaps itself.
417+ use instanceof EntireAllocationMemoryLocation and
418+ result instanceof MustExactlyOverlap
419+ or
420+ // EntireAllocationMemoryLocation totally overlaps any location within the same virtual
421+ // variable.
422+ not use instanceof EntireAllocationMemoryLocation and
423+ result instanceof MustTotallyOverlap
424+ )
425+ or
357426 exists ( VariableMemoryLocation defVariableLocation |
358427 defVariableLocation = def and
359428 (
360429 // A VariableMemoryLocation may partially overlap an unknown location within the same
361430 // virtual variable.
362431 def .getVirtualVariable ( ) = use .getVirtualVariable ( ) and
363- ( use instanceof UnknownMemoryLocation or use instanceof AllAliasedMemory ) and
432+ (
433+ use instanceof UnknownMemoryLocation or
434+ use instanceof AllAliasedMemory or
435+ use instanceof EntireAllocationMemoryLocation
436+ ) and
364437 result instanceof MayPartiallyOverlap
365438 or
366439 // A VariableMemoryLocation that is not a local variable may partially overlap an
@@ -421,19 +494,19 @@ private predicate isRelatableMemoryLocation(VariableMemoryLocation vml) {
421494 vml .getStartBitOffset ( ) != Ints:: unknown ( )
422495}
423496
424- private predicate isCoveredOffset ( IRVariable var , int offsetRank , VariableMemoryLocation vml ) {
497+ private predicate isCoveredOffset ( Allocation var , int offsetRank , VariableMemoryLocation vml ) {
425498 exists ( int startRank , int endRank , VirtualVariable vvar |
426499 vml .getStartBitOffset ( ) = rank [ startRank ] ( IntValue offset_ | isRelevantOffset ( vvar , offset_ ) ) and
427500 vml .getEndBitOffset ( ) = rank [ endRank ] ( IntValue offset_ | isRelevantOffset ( vvar , offset_ ) ) and
428- var = vml .getVariable ( ) and
501+ var = vml .getAllocation ( ) and
429502 vvar = vml .getVirtualVariable ( ) and
430503 isRelatableMemoryLocation ( vml ) and
431504 offsetRank in [ startRank .. endRank ]
432505 )
433506}
434507
435- private predicate hasUnknownOffset ( IRVariable var , VariableMemoryLocation vml ) {
436- vml .getVariable ( ) = var and
508+ private predicate hasUnknownOffset ( Allocation var , VariableMemoryLocation vml ) {
509+ vml .getAllocation ( ) = var and
437510 (
438511 vml .getStartBitOffset ( ) = Ints:: unknown ( ) or
439512 vml .getEndBitOffset ( ) = Ints:: unknown ( )
@@ -443,14 +516,14 @@ private predicate hasUnknownOffset(IRVariable var, VariableMemoryLocation vml) {
443516private predicate overlappingIRVariableMemoryLocations (
444517 VariableMemoryLocation def , VariableMemoryLocation use
445518) {
446- exists ( IRVariable var , int offsetRank |
519+ exists ( Allocation var , int offsetRank |
447520 isCoveredOffset ( var , offsetRank , def ) and
448521 isCoveredOffset ( var , offsetRank , use )
449522 )
450523 or
451- hasUnknownOffset ( use .getVariable ( ) , def )
524+ hasUnknownOffset ( use .getAllocation ( ) , def )
452525 or
453- hasUnknownOffset ( def .getVariable ( ) , use )
526+ hasUnknownOffset ( def .getAllocation ( ) , use )
454527}
455528
456529private Overlap getVariableMemoryLocationOverlap (
@@ -467,16 +540,20 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
467540 ( if instr .hasResultMayMemoryAccess ( ) then isMayAccess = true else isMayAccess = false ) and
468541 (
469542 (
470- kind . usesAddressOperand ( ) and
543+ isIndirectOrBufferMemoryAccess ( kind ) and
471544 if hasResultMemoryAccess ( instr , _, _, _, _, _, _)
472545 then
473- exists ( IRVariable var , IRType type , IntValue startBitOffset , IntValue endBitOffset |
546+ exists ( Allocation var , IRType type , IntValue startBitOffset , IntValue endBitOffset |
474547 hasResultMemoryAccess ( instr , var , type , _, startBitOffset , endBitOffset , isMayAccess ) and
475548 result = TVariableMemoryLocation ( var , type , _, startBitOffset , endBitOffset , isMayAccess )
476549 )
477550 else result = TUnknownMemoryLocation ( instr .getEnclosingIRFunction ( ) , isMayAccess )
478551 )
479552 or
553+ kind instanceof EntireAllocationMemoryAccess and
554+ result = TEntireAllocationMemoryLocation ( getAddressOperandAllocation ( instr
555+ .getResultAddressOperand ( ) ) , isMayAccess )
556+ or
480557 kind instanceof EscapedMemoryAccess and
481558 result = TAllAliasedMemory ( instr .getEnclosingIRFunction ( ) , isMayAccess )
482559 or
@@ -492,16 +569,20 @@ MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
492569 ( if operand .hasMayReadMemoryAccess ( ) then isMayAccess = true else isMayAccess = false ) and
493570 (
494571 (
495- kind . usesAddressOperand ( ) and
572+ isIndirectOrBufferMemoryAccess ( kind ) and
496573 if hasOperandMemoryAccess ( operand , _, _, _, _, _, _)
497574 then
498- exists ( IRVariable var , IRType type , IntValue startBitOffset , IntValue endBitOffset |
575+ exists ( Allocation var , IRType type , IntValue startBitOffset , IntValue endBitOffset |
499576 hasOperandMemoryAccess ( operand , var , type , _, startBitOffset , endBitOffset , isMayAccess ) and
500577 result = TVariableMemoryLocation ( var , type , _, startBitOffset , endBitOffset , isMayAccess )
501578 )
502579 else result = TUnknownMemoryLocation ( operand .getEnclosingIRFunction ( ) , isMayAccess )
503580 )
504581 or
582+ kind instanceof EntireAllocationMemoryAccess and
583+ result = TEntireAllocationMemoryLocation ( getAddressOperandAllocation ( operand
584+ .getAddressOperand ( ) ) , isMayAccess )
585+ or
505586 kind instanceof EscapedMemoryAccess and
506587 result = TAllAliasedMemory ( operand .getEnclosingIRFunction ( ) , isMayAccess )
507588 or
0 commit comments