Skip to content

Commit

Permalink
sdf
Browse files Browse the repository at this point in the history
  • Loading branch information
hvitved committed Oct 24, 2023
1 parent c330f9f commit 741725b
Show file tree
Hide file tree
Showing 5 changed files with 1,485 additions and 1,667 deletions.
3 changes: 1 addition & 2 deletions config/identical-files.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
"java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll",
"go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll",
"ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll",
"python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll",
"swift/ql/lib/codeql/swift/dataflow/internal/FlowSummaryImpl.qll"
],
Expand Down Expand Up @@ -534,4 +533,4 @@
"python/ql/test/experimental/dataflow/model-summaries/InlineTaintTest.ext.yml",
"python/ql/test/experimental/dataflow/model-summaries/NormalDataflowTest.ext.yml"
]
}
}
3 changes: 2 additions & 1 deletion ruby/ql/lib/codeql/ruby/dataflow/FlowSummary.qll
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ deprecated class SummaryComponentStack = Impl::Private::SummaryComponentStack;

/**
* DEPRECATED.
*
* Provides predicates for constructing stacks of summary components.
*/
deprecated module SummaryComponentStack {
Expand Down Expand Up @@ -145,7 +146,7 @@ abstract class SummarizedCallable extends LibraryCallable, Impl::Public::Summari
DataFlow::ParameterNode getParameter(string s) {
exists(ParameterPosition pos |
DataFlowImplCommon::parameterNode(result, TLibraryCallable(this), pos) and
s = Impl::InputStep1::getParameterPosition(pos)
s = Impl::Input::encodeParameterPosition(pos)
)
}
}
Expand Down
196 changes: 39 additions & 157 deletions ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@ private import codeql.ruby.dataflow.internal.DataFlowImplSpecific as DataFlowImp
private import DataFlowImplSpecific::Private
private import DataFlowImplSpecific::Public

module InputStep1 implements InputStep1Sig<DataFlowImplSpecific::RubyDataFlow> {
module Input implements InputSig<DataFlowImplSpecific::RubyDataFlow> {
class SummarizedCallableBase = string;

bindingset[c]
string summarizedCallableBaseToString(SummarizedCallableBase c) { result = c }

ArgumentPosition callbackSelfParameterPosition() { result.isLambdaSelf() }

DataFlowType getContentType(ContentSet c) { result = TUnknownDataFlowType() and exists(c) }
Expand All @@ -39,7 +36,9 @@ module InputStep1 implements InputStep1Sig<DataFlowImplSpecific::RubyDataFlow> {
result = TUnknownDataFlowType() and exists(t) and exists(rk)
}

string getParameterPosition(ParameterPosition pos) {
ReturnKind getStandardReturnValueKind() { result instanceof NormalReturnKind }

string encodeParameterPosition(ParameterPosition pos) {
exists(int i |
pos.isPositional(i) and
result = i.toString()
Expand Down Expand Up @@ -77,7 +76,7 @@ module InputStep1 implements InputStep1Sig<DataFlowImplSpecific::RubyDataFlow> {
result = "splat"
}

string getArgumentPosition(ArgumentPosition pos) {
string encodeArgumentPosition(ArgumentPosition pos) {
pos.isSelf() and result = "self"
or
pos.isLambdaSelf() and result = "lambda-self"
Expand All @@ -93,194 +92,77 @@ module InputStep1 implements InputStep1Sig<DataFlowImplSpecific::RubyDataFlow> {
pos.isKeyword(name) and
result = name + ":"
)
}

ReturnKind getReturnValueKind() { result instanceof NormalReturnKind }

bindingset[s]
ArgumentPosition parseParamBody(string s) {
result.isPositional(AccessPath::parseInt(s))
or
exists(string name |
s = name + ":" and
result.isKeyword(name)
)
or
s = "self" and
result.isSelf()
or
s = "lambda-self" and
result.isLambdaSelf()
or
s = "block" and
result.isBlock()
or
s = "any" and
result.isAny()
or
s = "any-named" and
result.isAnyNamed()
}

bindingset[s]
ParameterPosition parseArgBody(string s) {
result.isPositional(AccessPath::parseInt(s))
or
result.isPositionalLowerBound(AccessPath::parseLowerBound(s))
or
exists(string name |
s = name + ":" and
result.isKeyword(name)
)
or
s = "self" and
result.isSelf()
or
s = "lambda-self" and
result.isLambdaSelf()
or
s = "block" and
result.isBlock()
or
s = "any" and
result.isAny()
or
s = "any-named" and
result.isAnyNamed()
}
}

import MakeStep1<DataFlowImplSpecific::RubyDataFlow, InputStep1>

module InputStep2 implements InputStep2Sig {
bindingset[arg]
private ContentSet interpretElementArg(string arg) {
arg = "?" and
result = TSingletonContent(TUnknownElementContent())
or
arg = "any" and
result = TAnyElementContent()
or
exists(int lower, boolean includeUnknown |
lower =
AccessPath::parseLowerBound(ParsePositions::adjustElementArgument(arg, includeUnknown)) and
result = TElementLowerBoundContent(lower, includeUnknown)
)
or
exists(ConstantValue cv, string argAdjusted, boolean includeUnknown |
argAdjusted = ParsePositions::adjustElementArgument(arg, includeUnknown) and
(
includeUnknown = false and
result = TSingletonContent(TKnownElementContent(cv))
or
includeUnknown = true and
result = TKnownOrUnknownElementContent(TKnownElementContent(cv))
)
|
cv.isInt(AccessPath::parseInt(argAdjusted))
or
not exists(AccessPath::parseInt(argAdjusted)) and
cv.serialize() = argAdjusted
)
}

bindingset[c]
ContentSet interpretContentSummaryComponent(AccessPath::AccessPathTokenBase c) {
result = interpretElementArg(c.getAnArgument("Element"))
pos.isAny() and
result = "any"
or
result = TSingletonContent(TFieldContent(c.getAnArgument("Field")))
pos.isAnyNamed() and
result = "any-named"
}

bindingset[c]
ArgumentPosition interpretParameterSummaryComponent(AccessPath::AccessPathTokenBase c) { none() }

bindingset[c]
ParameterPosition interpretArgumentSummaryComponent(AccessPath::AccessPathTokenBase c) {
exists(string arg | arg = c.getAnArgument("Argument") |
arg = "any" and
result.isAny()
or
result.isPositionalLowerBound(AccessPath::parseLowerBound(arg))
string encodeContent(ContentSet cs, string arg) {
exists(Content c | cs = TSingletonContent(c) |
c = TFieldContent(arg) and result = "Field"
or
arg = "hash-splat" and
result.isHashSplat()
exists(ConstantValue cv |
c = TKnownElementContent(cv) and
result = "Element" and
arg = cv.serialize() + "!"
)
or
arg = "splat" and
result.isSplat(0)
)
}

bindingset[c]
ContentSet interpretWithoutContentSummaryComponent(AccessPath::AccessPathTokenBase c) {
result = interpretElementArg(c.getAnArgument("WithoutElement"))
}

bindingset[c]
ContentSet interpretWithContentSummaryComponent(AccessPath::AccessPathTokenBase c) {
result = interpretElementArg(c.getAnArgument("WithElement"))
}

private string getContentSpecific(Content c) {
exists(string name | c = TFieldContent(name) and result = "Field[" + name + "]")
or
exists(ConstantValue cv |
c = TKnownElementContent(cv) and result = "Element[" + cv.serialize() + "!]"
c = TUnknownElementContent() and result = "Element" and arg = "?"
)
or
c = TUnknownElementContent() and result = "Element[?]"
}

string getContentMadRepresentation(ContentSet cs) {
exists(Content c | cs = TSingletonContent(c) and result = getContentSpecific(c))
or
cs = TAnyElementContent() and result = "Element[any]"
cs = TAnyElementContent() and result = "Element" and arg = "any"
or
exists(Content::KnownElementContent kec |
cs = TKnownOrUnknownElementContent(kec) and
result = "Element[" + kec.getIndex().serialize() + "]"
result = "Element" and
arg = kec.getIndex().serialize()
)
or
exists(int lower, boolean includeUnknown, string unknown |
cs = TElementLowerBoundContent(lower, includeUnknown) and
(if includeUnknown = true then unknown = "" else unknown = "!") and
result = "Element[" + lower + ".." + unknown + "]"
result = "Element" and
arg = lower.toString() + ".." + unknown
)
}

string getReturnMadRepresentation(ReturnKind rk) {
not rk = InputStep1::getReturnValueKind() and
result = "ReturnValue[" + rk + "]"
string encodeReturn(ReturnKind rk, string arg) {
not rk = Input::getStandardReturnValueKind() and
result = "ReturnValue" and
arg = rk.toString()
}

string getWithoutContentMadRepresentation(ContentSet c) {
result = "WithoutElement[" + getContentMadRepresentation(c) + "]"
string encodeWithoutContent(ContentSet c, string arg) {
result = "Without" + encodeContent(c, arg)
}

string getWithContentMadRepresentation(ContentSet c) {
result = "WithElement[" + getContentMadRepresentation(c) + "]"
}
string encodeWithContent(ContentSet c, string arg) { result = "With" + encodeContent(c, arg) }
}

import MakeStep2<InputStep2> as Step2
private import Make<DataFlowImplSpecific::RubyDataFlow, Input> as Impl

module InputStep3 implements Step2::Private::InputStep3Sig {
DataFlowType getSyntheticGlobalType(Step2::Private::SyntheticGlobal sg) {
private module StepsInput implements Impl::Private::StepsInputSig {
DataFlowType getSyntheticGlobalType(Private::SyntheticGlobal sg) {
result = TUnknownDataFlowType() and exists(sg)
}

DataFlowCall getACall(Step2::Public::SummarizedCallable sc) {
DataFlowCall getACall(Public::SummarizedCallable sc) {
result.asCall().getAstNode() = sc.(LibraryCallable).getACall()
or
result.asCall().getAstNode() = sc.(LibraryCallable).getACallSimple()
}
}

module Private {
import Step2::Private
import MakeStep3<InputStep3>
import Impl::Private

module Steps = Impl::Private::Steps<StepsInput>;
}

module Public = Step2::Public;
module Public = Impl::Public;

module ParsePositions {
private import Private
Expand Down Expand Up @@ -323,7 +205,7 @@ module ParsePositions {
}

bindingset[arg]
string adjustElementArgument(string arg, boolean includeUnknown) {
private string adjustElementArgument(string arg, boolean includeUnknown) {
result = arg.regexpCapture("(.*)!", 1) and
includeUnknown = false
or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,13 @@ API::Node getExtraSuccessorFromNode(API::Node node, AccessPathTokenBase token) {
or
token.getName() = "Parameter" and
exists(DataFlowDispatch::ArgumentPosition argPos, DataFlowDispatch::ParameterPosition paramPos |
argPos = FlowSummaryImpl::InputStep1::parseParamBody(token.getAnArgument()) and
token.getAnArgument() = FlowSummaryImpl::Input::encodeArgumentPosition(argPos) and
DataFlowDispatch::parameterMatch(paramPos, argPos) and
result = node.getParameterAtPosition(paramPos)
)
or
exists(DataFlow::ContentSet contents |
contents = FlowSummaryImpl::InputStep2::interpretContentSummaryComponent(token) and
exists(DataFlow::ContentSet contents, string name |
name = FlowSummaryImpl::Input::encodeContent(contents, token.getAnArgument(name)) and
result = node.getContents(contents)
)
}
Expand All @@ -168,7 +168,7 @@ bindingset[token]
API::Node getExtraSuccessorFromInvoke(InvokeNode node, AccessPathTokenBase token) {
token.getName() = "Argument" and
exists(DataFlowDispatch::ArgumentPosition argPos, DataFlowDispatch::ParameterPosition paramPos |
paramPos = FlowSummaryImpl::InputStep1::parseArgBody(token.getAnArgument()) and
token.getAnArgument() = FlowSummaryImpl::Input::encodeParameterPosition(paramPos) and
DataFlowDispatch::parameterMatch(paramPos, argPos) and
result = node.getArgumentAtPosition(argPos)
)
Expand Down
Loading

0 comments on commit 741725b

Please sign in to comment.