Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C#: Initial implementation of csv printing in FlowSummaries test #7178

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
@@ -383,7 +383,7 @@ class Parameterizable extends DotNet::Parameterizable, Declaration, @parameteriz
override Parameter getParameter(int i) { params(result, _, _, i, _, this, _) }

/**
* Gets the name of this parameter followed by its type, possibly prefixed
* Gets the type of the parameter, possibly prefixed
* with `out`, `ref`, or `params`, where appropriate.
*/
private string parameterTypeToString(int i) {
@@ -127,6 +127,38 @@ module Public {
SummaryComponentStack return(ReturnKind rk) { result = singleton(SummaryComponent::return(rk)) }
}

private predicate noComponentSpecificCsv(SummaryComponent sc) {
not exists(getComponentSpecificCsv(sc))
}

/** Gets a textual representation of this component used for flow summaries. */
private string getComponentCsv(SummaryComponent sc) {
result = getComponentSpecificCsv(sc)
or
noComponentSpecificCsv(sc) and
(
exists(int i | sc = TParameterSummaryComponent(i) and result = "Parameter[" + i + "]")
or
exists(int i | sc = TArgumentSummaryComponent(i) and result = "Argument[" + i + "]")
or
sc = TReturnSummaryComponent(getReturnValueKind()) and result = "ReturnValue"
)
}

/** Gets a textual representation of this stack used for flow summaries. */
string getComponentStackCsv(SummaryComponentStack stack) {
exists(SummaryComponent head, SummaryComponentStack tail |
head = stack.head() and
tail = stack.tail() and
result = getComponentCsv(head) + " of " + getComponentStackCsv(tail)
)
or
exists(SummaryComponent c |
stack = TSingletonSummaryComponentStack(c) and
result = getComponentCsv(c)
)
}

/**
* A class that exists for QL technical reasons only (the IPA type used
* to represent component stacks needs to be bounded).
@@ -970,18 +1002,31 @@ module Private {
module TestOutput {
/** A flow summary to include in the `summary/3` query predicate. */
abstract class RelevantSummarizedCallable extends SummarizedCallable {
/** Gets the string representation of this callable used by `summary/3`. */
string getFullString() { result = this.toString() }
/** Gets the string representation of this callable used by `summary/1`. */
abstract string getCallableCsv();
}

/** A query predicate for outputting flow summaries in QL tests. */
query predicate summary(string callable, string flow, boolean preservesValue) {
/** Render the kind in the format used in flow summaries. */
private string renderKind(boolean preservesValue) {
preservesValue = true and result = "value"
or
preservesValue = false and result = "taint"
}

/**
* A query predicate for outputting flow summaries in semi-colon separated format in QL tests.
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind",
* ext is hardcoded to empty.
*/
query predicate summary(string csv) {
exists(
RelevantSummarizedCallable c, SummaryComponentStack input, SummaryComponentStack output
RelevantSummarizedCallable c, SummaryComponentStack input, SummaryComponentStack output,
boolean preservesValue
|
callable = c.getFullString() and
c.propagatesFlow(input, output, preservesValue) and
flow = input + " -> " + output
csv =
c.getCallableCsv() + ";;" + getComponentStackCsv(input) + ";" +
getComponentStackCsv(output) + ";" + renderKind(preservesValue)
)
}
}
@@ -138,6 +138,26 @@ SummaryComponent interpretComponentSpecific(string c) {
)
}

/** Gets the textual representation of the content in the format used for flow summaries. */
private string getContentSpecificCsv(Content c) {
c = TElementContent() and result = "Element"
or
exists(Field f | c = TFieldContent(f) and result = "Field[" + f.getQualifiedName() + "]")
or
exists(Property p | c = TPropertyContent(p) and result = "Property[" + p.getQualifiedName() + "]")
}

/** Gets the textual representation of a summary component in the format used for flow summaries. */
string getComponentSpecificCsv(SummaryComponent sc) {
exists(Content c | sc = TContentSummaryComponent(c) and result = getContentSpecificCsv(c))
or
exists(ReturnKind rk |
sc = TReturnSummaryComponent(rk) and
result = "ReturnValue[" + rk + "]" and
not rk instanceof NormalReturnKind
)
}

class SourceOrSinkElement = Element;

/** Gets the return kind corresponding to specification `"ReturnValue"`. */
Loading
Loading