@@ -37,6 +37,37 @@ class SsaSourceVariable extends LocalVariable {
3737 }
3838}
3939
40+ /**
41+ * A variable that can be SSA converted, that is, a global variable
42+ */
43+ class SsaGlobalSourceVariable extends DeclaredVariable {
44+ SsaGlobalSourceVariable ( ) { not this .getScope ( ) instanceof LocalScope }
45+
46+ /**
47+ * Holds if there may be indirect references of this variable that are not covered by `getAReference()`.
48+ *
49+ * This is the case for variables that have their address taken, and for variables whose
50+ * name resolution information may be incomplete (for instance due to an extractor error).
51+ */
52+ predicate mayHaveIndirectReferences ( ) {
53+ // variables that have their address taken
54+ exists ( AddressExpr addr | addr .getOperand ( ) .stripParens ( ) = this .getAReference ( ) )
55+ or
56+ exists ( DataFlow:: MethodReadNode mrn |
57+ mrn .getReceiver ( ) = this .getARead ( ) and
58+ mrn .getMethod ( ) .getReceiverType ( ) instanceof PointerType
59+ )
60+ or
61+ // variables where there is an unresolved reference with the same name in the same
62+ // scope or a nested scope, suggesting that name resolution information may be incomplete
63+ exists ( FunctionScope scope , FuncDef inner |
64+ scope = this .getScope ( ) .( LocalScope ) .getEnclosingFunctionScope ( ) and
65+ unresolvedReference ( this .getName ( ) , inner ) and
66+ inner .getScope ( ) .getOuterScope * ( ) = scope
67+ )
68+ }
69+ }
70+
4071/**
4172 * Holds if there is an unresolved reference to `name` in `fn`.
4273 */
@@ -99,6 +130,48 @@ class SsaVariable extends TSsaDefinition {
99130 }
100131}
101132
133+
134+ /**
135+ * A global SSA variable.
136+ */
137+ class SsaGlobalVariable extends TGlobalSsaDefinition {
138+ /** Gets the source variable corresponding to this SSA variable. */
139+ SsaGlobalSourceVariable getSourceVariable ( ) { result = this .( SsaGlobalDefinition ) .getSourceVariable ( ) }
140+
141+ /** Gets the (unique) definition of this SSA variable. */
142+ SsaGlobalDefinition getDefinition ( ) { result = this }
143+
144+ /** Gets the type of this SSA variable. */
145+ Type getType ( ) { result = this .getSourceVariable ( ) .getType ( ) }
146+
147+ /** Gets a use in basic block `bb` that refers to this SSA variable. */
148+ IR:: Instruction getAUseIn ( ReachableBasicBlock bb ) {
149+ exists ( int i , SsaGlobalSourceVariable v | v = this .getSourceVariable ( ) |
150+ result = bb .getNode ( i ) and
151+ this = getGlobalDefinition ( bb , i , v )
152+ )
153+ }
154+
155+ /** Gets a use that refers to this SSA variable. */
156+ IR:: Instruction getAUse ( ) { result = this .getAUseIn ( _) }
157+
158+ /** Gets a textual representation of this element. */
159+ string toString ( ) { result = this .getDefinition ( ) .prettyPrintRef ( ) }
160+
161+ /**
162+ * Holds if this element is at the specified location.
163+ * The location spans column `startcolumn` of line `startline` to
164+ * column `endcolumn` of line `endline` in file `filepath`.
165+ * For more information, see
166+ * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
167+ */
168+ predicate hasLocationInfo (
169+ string filepath , int startline , int startcolumn , int endline , int endcolumn
170+ ) {
171+ this .getDefinition ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn )
172+ }
173+ }
174+
102175/**
103176 * An SSA definition.
104177 */
@@ -156,6 +229,63 @@ class SsaDefinition extends TSsaDefinition {
156229 ) ;
157230}
158231
232+ /**
233+ * A global SSA definition.
234+ */
235+ class SsaGlobalDefinition extends TGlobalSsaDefinition {
236+ /** Gets the SSA variable defined by this definition. */
237+ SsaGlobalVariable getVariable ( ) { result = this }
238+
239+ /** Gets the source variable defined by this definition. */
240+ abstract SsaGlobalSourceVariable getSourceVariable ( ) ;
241+
242+ /**
243+ * Gets the basic block to which this definition belongs.
244+ */
245+ abstract ReachableBasicBlock getBasicBlock ( ) ;
246+
247+ /**
248+ * INTERNAL: Use `getBasicBlock()` and `getSourceVariable()` instead.
249+ *
250+ * Holds if this is a definition of source variable `v` at index `idx` in basic block `bb`.
251+ *
252+ * Phi nodes are considered to be at index `-1`, all other definitions at the index of
253+ * the control flow node they correspond to.
254+ */
255+ abstract predicate definesAt ( ReachableBasicBlock bb , int idx , SsaSourceVariable v ) ;
256+
257+ /**
258+ * INTERNAL: Use `toString()` instead.
259+ *
260+ * Gets a pretty-printed representation of this SSA definition.
261+ */
262+ abstract string prettyPrintDef ( ) ;
263+
264+ /**
265+ * INTERNAL: Do not use.
266+ *
267+ * Gets a pretty-printed representation of a reference to this SSA definition.
268+ */
269+ abstract string prettyPrintRef ( ) ;
270+
271+ /** Gets the innermost function or file to which this SSA definition belongs. */
272+ ControlFlow:: Root getRoot ( ) { result = this .getBasicBlock ( ) .getRoot ( ) }
273+
274+ /** Gets a textual representation of this element. */
275+ string toString ( ) { result = this .prettyPrintDef ( ) }
276+
277+ /**
278+ * Holds if this element is at the specified location.
279+ * The location spans column `startcolumn` of line `startline` to
280+ * column `endcolumn` of line `endline` in file `filepath`.
281+ * For more information, see
282+ * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
283+ */
284+ abstract predicate hasLocationInfo (
285+ string filepath , int startline , int startcolumn , int endline , int endcolumn
286+ ) ;
287+ }
288+
159289/**
160290 * An SSA definition that corresponds to an explicit assignment or other variable definition.
161291 */
@@ -302,6 +432,14 @@ class SsaPhiNode extends SsaPseudoDefinition, TPhi {
302432 }
303433}
304434
435+
436+ /**
437+ * An SSA variable, possibly with a chain of field reads on it.
438+ */
439+ private newtype TGlobalSsaWithFields =
440+ TGlobalRoot ( SsaGlobalVariable v ) or
441+ TGlobalStep ( GlobalWithFields base , Field f ) { exists ( accessPathAux ( base , f ) ) }
442+
305443/**
306444 * An SSA variable, possibly with a chain of field reads on it.
307445 */
@@ -401,6 +539,75 @@ class SsaWithFields extends TSsaWithFields {
401539 }
402540}
403541
542+
543+ /** An SSA variable with zero or more fields read from it. */
544+ class GlobalWithFields extends TSsaWithFields {
545+ /**
546+ * Gets the SSA variable corresponding to the base of this SSA variable with fields.
547+ *
548+ * For example, the SSA variable corresponding to `a` for the SSA variable with fields
549+ * corresponding to `a.b`.
550+ */
551+ SsaVariable getBaseVariable ( ) {
552+ this = TRoot ( result )
553+ or
554+ exists ( GlobalWithFields base | this = TStep ( base , _) | result = base .getBaseVariable ( ) )
555+ }
556+
557+ /** Gets a use that refers to this SSA variable with fields. */
558+ DataFlow:: Node getAUse ( ) { this = accessPath ( result .asInstruction ( ) ) }
559+
560+ /** Gets the type of this SSA variable with fields. */
561+ Type getType ( ) {
562+ exists ( SsaVariable var | this = TRoot ( var ) | result = var .getType ( ) )
563+ or
564+ exists ( Field f | this = TStep ( _, f ) | result = f .getType ( ) )
565+ }
566+
567+ /** Gets a textual representation of this element. */
568+ string toString ( ) {
569+ exists ( SsaVariable var | this = TRoot ( var ) | result = "(" + var + ")" )
570+ or
571+ exists ( GlobalWithFields base , Field f | this = TStep ( base , f ) | result = base + "." + f .getName ( ) )
572+ }
573+
574+ /**
575+ * Gets an SSA-with-fields variable that is similar to this SSA-with-fields variable in the
576+ * sense that it has the same root variable and the same sequence of field accesses.
577+ */
578+ GlobalWithFields similar ( ) {
579+ result .getBaseVariable ( ) .getSourceVariable ( ) = this .getBaseVariable ( ) .getSourceVariable ( ) and
580+ result .getQualifiedName ( ) = this .getQualifiedName ( )
581+ }
582+
583+ /**
584+ * Gets the qualified name of the source variable or variable and fields that this represents.
585+ *
586+ * For example, for an SSA variable that represents the field `a.b`, this would get the string
587+ * `"a.b"`.
588+ */
589+ string getQualifiedName ( ) {
590+ exists ( SsaVariable v | this = TRoot ( v ) and result = v .getSourceVariable ( ) .getName ( ) )
591+ or
592+ exists ( GlobalWithFields base , Field f | this = TStep ( base , f ) |
593+ result = base .getQualifiedName ( ) + "." + f .getName ( )
594+ )
595+ }
596+
597+ /**
598+ * Holds if this element is at the specified location.
599+ * The location spans column `startcolumn` of line `startline` to
600+ * column `endcolumn` of line `endline` in file `filepath`.
601+ * For more information, see
602+ * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
603+ */
604+ predicate hasLocationInfo (
605+ string filepath , int startline , int startcolumn , int endline , int endcolumn
606+ ) {
607+ this .getBaseVariable ( ) .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn )
608+ }
609+ }
610+
404611/**
405612 * Gets a read similar to `node`, according to the same rules as `SsaWithFields.similar()`.
406613 */
0 commit comments