From aeb98401445e42213280398de011f67242ced054 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Mon, 6 Jan 2020 15:36:54 +0000 Subject: [PATCH] Add `SliceNode` class. --- ql/src/semmle/go/controlflow/IR.qll | 21 ++++++++++ .../go/dataflow/internal/DataFlowUtil.qll | 41 +++++++++++++++---- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/ql/src/semmle/go/controlflow/IR.qll b/ql/src/semmle/go/controlflow/IR.qll index 7de15bb3b1d..0b37deadbbd 100644 --- a/ql/src/semmle/go/controlflow/IR.qll +++ b/ql/src/semmle/go/controlflow/IR.qll @@ -1413,4 +1413,25 @@ module IR { ExtractTupleElementInstruction extractTupleElement(Instruction base, int idx) { result.extractsElement(base, idx) } + + /** + * Gets the instruction corresponding to the implicit lower bound of slice `e`, if any. + */ + EvalImplicitLowerSliceBoundInstruction implicitLowerSliceBoundInstruction(SliceExpr e) { + result = MkImplicitLowerSliceBound(e) + } + + /** + * Gets the instruction corresponding to the implicit upper bound of slice `e`, if any. + */ + EvalImplicitUpperSliceBoundInstruction implicitUpperSliceBoundInstruction(SliceExpr e) { + result = MkImplicitUpperSliceBound(e) + } + + /** + * Gets the instruction corresponding to the implicit maximum bound of slice `e`, if any. + */ + EvalImplicitMaxSliceBoundInstruction implicitMaxSliceBoundInstruction(SliceExpr e) { + result = MkImplicitMaxSliceBound(e) + } } diff --git a/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll b/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll index 69e1383187f..6f53a53686e 100644 --- a/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll +++ b/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll @@ -112,9 +112,7 @@ class Node extends TNode { * Holds if the result of this instruction is known at compile time, and is guaranteed not to * depend on the platform where it is evaluated. */ - predicate isPlatformIndependentConstant() { - this.asInstruction().isPlatformIndependentConstant() - } + predicate isPlatformIndependentConstant() { this.asInstruction().isPlatformIndependentConstant() } /** * Gets a data-flow node to which data may flow from this node in one (intra-procedural) step. @@ -449,7 +447,7 @@ class ReadNode extends InstructionNode { /** * Holds if this data-flow node evaluates to value of `v`, which is a value entity, that is, a - * constant, variable, field, function, or method. + * constant, variable, field, function, or method. */ predicate reads(ValueEntity v) { insn.reads(v) } @@ -492,6 +490,35 @@ class ElementReadNode extends ReadNode { predicate reads(Node base, Node index) { getBase() = base and getIndex() = index } } +/** + * A data-flow node that extracts a substring or slice from a string, array, pointer to array, + * or slice. + */ +class SliceNode extends ExprNode { + override SliceExpr expr; + + /** Gets the base of this slice node. */ + Node getBase() { result = exprNode(expr.getBase()) } + + /** Gets the lower bound of this slice node. */ + Node getLow() { + result = exprNode(expr.getLow()) or + result = instructionNode(IR::implicitLowerSliceBoundInstruction(expr)) + } + + /** Gets the upper bound of this slice node. */ + Node getHigh() { + result = exprNode(expr.getHigh()) or + result = instructionNode(IR::implicitUpperSliceBoundInstruction(expr)) + } + + /** Gets the maximum of this slice node. */ + Node getMax() { + result = exprNode(expr.getMax()) or + result = instructionNode(IR::implicitMaxSliceBoundInstruction(expr)) + } +} + /** * A data-flow node corresponding to an expression with a binary operator. */ @@ -512,7 +539,7 @@ class BinaryOperationNode extends Node { | left = exprNode(assgn.getLhs()) and right = exprNode(assgn.getRhs()) and - op = o.substring(0, o.length()-1) + op = o.substring(0, o.length() - 1) ) or exists(IR::EvalIncDecRhsInstruction rhs, IncDecStmt ids | @@ -683,9 +710,7 @@ Node extractTupleElement(Node t, int i) { * Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local * (intra-procedural) step. */ -predicate localFlowStep(Node nodeFrom, Node nodeTo) { - simpleLocalFlowStep(nodeFrom, nodeTo) -} +predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) } /** * INTERNAL: do not use.