Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit 1092fe5

Browse files
author
Sauyon Lee
committed
Move SsaWithFields to the Ssa file and rework it for public use
Also use it in OpenRedirect
1 parent 4c9bf22 commit 1092fe5

File tree

3 files changed

+102
-44
lines changed

3 files changed

+102
-44
lines changed

ql/src/semmle/go/dataflow/SSA.qll

+94
Original file line numberDiff line numberDiff line change
@@ -288,3 +288,97 @@ class SsaPhiNode extends SsaPseudoDefinition, TPhi {
288288
getBasicBlock().hasLocationInfo(filepath, startline, startcolumn, _, _)
289289
}
290290
}
291+
292+
/**
293+
* An SSA variable, possibly with a chain of field reads on it.
294+
*/
295+
private newtype TSsaWithFields =
296+
TRoot(SsaVariable v) or
297+
TStep(SsaWithFields base, Field f) { exists(accessPathAux(base, f)) }
298+
299+
/**
300+
* Gets a representation of `nd` as an ssa-with-fields value if there is one.
301+
*/
302+
private TSsaWithFields accessPath(IR::Instruction insn) {
303+
exists(SsaVariable v | insn = v.getAUse() | result = TRoot(v))
304+
or
305+
exists(SsaWithFields base, Field f | insn = accessPathAux(base, f) | result = TStep(base, f))
306+
}
307+
308+
/**
309+
* Gets a data-flow node that reads a field `f` from a node that is represented
310+
* by ssa-with-fields value `base`.
311+
*/
312+
private IR::Instruction accessPathAux(TSsaWithFields base, Field f) {
313+
exists(IR::FieldReadInstruction fr | fr = result |
314+
base = accessPath(fr.getBase()) and
315+
f = fr.getField()
316+
)
317+
}
318+
319+
abstract class SsaWithFields extends TSsaWithFields {
320+
/**
321+
* Gets the SSA variable corresponding to the base of this SSA variable with fields.
322+
*
323+
* For example, the SSA variable corresponding to `a` for the SSA variable with fields
324+
* corresponding to `a.b`.
325+
*/
326+
abstract SsaVariable getBaseVariable();
327+
328+
/** Gets the type of this SSA variable with fields. */
329+
abstract Type getType();
330+
331+
/** Gets a use in basic block `bb` that refers to this SSA variable with fields. */
332+
abstract IR::Instruction getAUseIn(ReachableBasicBlock bb);
333+
334+
/** Gets a use that refers to this SSA variable with fields. */
335+
IR::Instruction getAUse() { result = this.getAUseIn(_) }
336+
337+
/** Gets a textual representation of this element. */
338+
abstract string toString();
339+
340+
/**
341+
* Holds if this element is at the specified location.
342+
* The location spans column `startcolumn` of line `startline` to
343+
* column `endcolumn` of line `endline` in file `filepath`.
344+
* For more information, see
345+
* [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
346+
*/
347+
predicate hasLocationInfo(
348+
string filepath, int startline, int startcolumn, int endline, int endcolumn
349+
) {
350+
this.getBaseVariable().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
351+
}
352+
}
353+
354+
private class SsaWithFieldsRoot extends SsaWithFields, TRoot {
355+
SsaVariable self;
356+
357+
SsaWithFieldsRoot() { this = TRoot(self) }
358+
359+
override SsaVariable getBaseVariable() { result = self }
360+
361+
override Type getType() { result = self.getType() }
362+
363+
override IR::Instruction getAUseIn(ReachableBasicBlock bb) { result = self.getAUseIn(bb) }
364+
365+
override string toString() { result = "(" + self.toString() + ")" }
366+
}
367+
368+
private class SsaWithFieldsStep extends SsaWithFields, TStep {
369+
SsaWithFields base;
370+
Field f;
371+
372+
SsaWithFieldsStep() { this = TStep(base, f) }
373+
374+
override SsaVariable getBaseVariable() { result = base.getBaseVariable() }
375+
376+
override Type getType() { result = f.getType() }
377+
378+
override IR::FieldReadInstruction getAUseIn(ReachableBasicBlock bb) {
379+
result.getBase() = base.getAUseIn(bb) and
380+
result.getField() = f
381+
}
382+
383+
override string toString() { result = base.toString() + "." + f.getName() }
384+
}

ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll

+5-31
Original file line numberDiff line numberDiff line change
@@ -733,33 +733,6 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) {
733733
*/
734734
predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
735735

736-
/**
737-
* An SSA variable, possibly with a chain of field reads on it.
738-
*/
739-
private newtype SsaWithFields =
740-
Root(SsaVariable v) or
741-
Step(SsaWithFields base, Field f) { exists(accessPathAux(base, f)) }
742-
743-
/**
744-
* Gets a representation of `nd` as an ssa-with-fields value if there is one.
745-
*/
746-
private SsaWithFields accessPath(Node nd) {
747-
exists(SsaVariable v | nd.asInstruction() = v.getAUse() | result = Root(v))
748-
or
749-
exists(SsaWithFields base, Field f | nd = accessPathAux(base, f) | result = Step(base, f))
750-
}
751-
752-
/**
753-
* Gets a data-flow node that reads a field `f` from a node that is represented
754-
* by ssa-with-fields value `base`.
755-
*/
756-
private Node accessPathAux(SsaWithFields base, Field f) {
757-
exists(IR::FieldReadInstruction fr | fr = result.asInstruction() |
758-
base = accessPath(instructionNode(fr.getBase())) and
759-
f = fr.getField()
760-
)
761-
}
762-
763736
/**
764737
* A guard that validates some expression.
765738
*
@@ -776,8 +749,10 @@ abstract class BarrierGuard extends Node {
776749
/** Gets a node guarded by this guard. */
777750
final Node getAGuardedNode() {
778751
exists(ControlFlow::ConditionGuardNode guard, Node nd |
779-
guards(guard, nd, accessPath(result)) and
780-
guard.dominates(result.asInstruction().getBasicBlock())
752+
exists(SsaWithFields var | result.asInstruction() = var.getAUse() |
753+
guards(guard, nd, var) and
754+
guard.dominates(result.asInstruction().getBasicBlock())
755+
)
781756
)
782757
}
783758

@@ -789,8 +764,7 @@ abstract class BarrierGuard extends Node {
789764
*/
790765
pragma[noinline]
791766
private predicate guards(ControlFlow::ConditionGuardNode guard, Node nd, SsaWithFields ap) {
792-
guards(guard, nd) and
793-
ap = accessPath(nd)
767+
guards(guard, nd) and nd.asInstruction() = ap.getAUse()
794768
}
795769

796770
/**

ql/src/semmle/go/security/OpenUrlRedirectCustomizations.qll

+3-13
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,6 @@ module OpenUrlRedirect {
5050
}
5151
}
5252

53-
/**
54-
* Holds if `a` and `b` read the same variable, field, or method.
55-
*/
56-
predicate readsSameEntity(Read a, Read b) {
57-
exists(DataFlow::Node aBase, DataFlow::Node bBase | readsSameEntity(aBase, bBase) |
58-
exists(Field f | a.readsField(aBase, f) | b.readsField(bBase, f))
59-
or
60-
exists(Method m | a.readsMethod(aBase, m) | b.readsMethod(bBase, m))
61-
)
62-
}
63-
6453
/**
6554
* An access to a variable that is preceded by an assignment to its `Path` field.
6655
*
@@ -69,10 +58,11 @@ module OpenUrlRedirect {
6958
*/
7059
class PathAssignmentBarrier extends Barrier, Read {
7160
PathAssignmentBarrier() {
72-
exists(Write w, Field f, Read writeBase, ValueEntity v |
61+
exists(Write w, Field f, Read writeBase, SsaWithFields var |
7362
f.getName() = "Path" and
7463
hasHostnameSanitizingSubstring(w.getRhs()) and
75-
readsSameEntity(this, writeBase)
64+
this.asInstruction() = var.getAUse() and
65+
writeBase.asInstruction() = var.getAUse()
7666
|
7767
w.writesField(writeBase, f, _) and
7868
w.getBasicBlock().(ReachableBasicBlock).dominates(this.asInstruction().getBasicBlock()) and

0 commit comments

Comments
 (0)