Skip to content

Commit a3ca9ad

Browse files
committed
C#: Sync flow summary implementation files and implement specific parts for ruby and java
1 parent e153a65 commit a3ca9ad

File tree

5 files changed

+134
-15
lines changed

5 files changed

+134
-15
lines changed

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ predicate simpleLocalFlowStep(Node node1, Node node2) {
164164
pragma[only_bind_out](node2.getEnclosingCallable())
165165
}
166166

167-
private newtype TContent =
167+
newtype TContent =
168168
TFieldContent(InstanceField f) or
169169
TArrayContent() or
170170
TCollectionContent() or

java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,38 @@ module Public {
127127
SummaryComponentStack return(ReturnKind rk) { result = singleton(SummaryComponent::return(rk)) }
128128
}
129129

130+
private predicate noComponentSpecificCsv(SummaryComponent sc) {
131+
not exists(getComponentSpecificCsv(sc))
132+
}
133+
134+
/** Gets a textual representation of this component used for flow summaries */
135+
private string getComponentCsv(SummaryComponent sc) {
136+
result = getComponentSpecificCsv(sc)
137+
or
138+
noComponentSpecificCsv(sc) and
139+
(
140+
exists(int i | sc = TParameterSummaryComponent(i) and result = "Parameter[" + i + "]")
141+
or
142+
exists(int i | sc = TArgumentSummaryComponent(i) and result = "Argument[" + i + "]")
143+
or
144+
sc = TReturnSummaryComponent(getReturnValueKind()) and result = "ReturnValue"
145+
)
146+
}
147+
148+
/** Gets a textual representation of this stack used for flow summaries. */
149+
string getComponentStackCsv(SummaryComponentStack stack) {
150+
exists(SummaryComponent head, SummaryComponentStack tail |
151+
head = stack.head() and
152+
tail = stack.tail() and
153+
result = getComponentCsv(head) + " of " + getComponentStackCsv(tail)
154+
)
155+
or
156+
exists(SummaryComponent c |
157+
stack = TSingletonSummaryComponentStack(c) and
158+
result = getComponentCsv(c)
159+
)
160+
}
161+
130162
/**
131163
* A class that exists for QL technical reasons only (the IPA type used
132164
* to represent component stacks needs to be bounded).
@@ -970,18 +1002,31 @@ module Private {
9701002
module TestOutput {
9711003
/** A flow summary to include in the `summary/3` query predicate. */
9721004
abstract class RelevantSummarizedCallable extends SummarizedCallable {
973-
/** Gets the string representation of this callable used by `summary/3`. */
974-
string getFullString() { result = this.toString() }
1005+
/** Gets the string representation of this callable used by `summary/1`. */
1006+
abstract string getCallableCsv();
9751007
}
9761008

977-
/** A query predicate for outputting flow summaries in QL tests. */
978-
query predicate summary(string callable, string flow, boolean preservesValue) {
1009+
/** Render the kind in the format used in flow summaries. */
1010+
private string renderKind(boolean preservesValue) {
1011+
preservesValue = true and result = "value"
1012+
or
1013+
preservesValue = false and result = "taint"
1014+
}
1015+
1016+
/**
1017+
* A query predicate for outputting flow summaries in semi-colon separated format in QL tests.
1018+
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind",
1019+
* ext is hardcoded to empty
1020+
*/
1021+
query predicate summary(string csv) {
9791022
exists(
980-
RelevantSummarizedCallable c, SummaryComponentStack input, SummaryComponentStack output
1023+
RelevantSummarizedCallable c, SummaryComponentStack input, SummaryComponentStack output,
1024+
boolean preservesValue
9811025
|
982-
callable = c.getFullString() and
9831026
c.propagatesFlow(input, output, preservesValue) and
984-
flow = input + " -> " + output
1027+
csv =
1028+
c.getCallableCsv() + ";;" + getComponentStackCsv(input) + ";" +
1029+
getComponentStackCsv(output) + ";" + renderKind(preservesValue)
9851030
)
9861031
}
9871032
}

java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,30 @@ SummaryComponent interpretComponentSpecific(string c) {
7272
exists(Content content | parseContent(c, content) and result = SummaryComponent::content(content))
7373
}
7474

75+
/** Gets the summary component for specification component `c`, if any. */
76+
private string getContentSpecificCsv(Content c) {
77+
exists(Field f, string package, string className, string fieldName |
78+
c = TFieldContent(f) and
79+
f.hasQualifiedName(package, className, fieldName) and
80+
result = "Field[" + package + "." + className + "." + fieldName + "]"
81+
)
82+
or
83+
exists(SyntheticField f | c = TSyntheticFieldContent(f) and result = "SyntheticField[" + f + "]")
84+
or
85+
c instanceof ArrayContent and result = "ArrayElement"
86+
or
87+
c instanceof CollectionContent and result = "Element"
88+
or
89+
c instanceof MapKeyContent and result = "MapKey"
90+
or
91+
c instanceof MapValueContent and result = "MapValue"
92+
}
93+
94+
/** Gets the textual representation of the content in the format used for flow summaries */
95+
string getComponentSpecificCsv(SummaryComponent sc) {
96+
exists(Content c | sc = TContentSummaryComponent(c) and result = getContentSpecificCsv(c))
97+
}
98+
7599
class SourceOrSinkElement = Top;
76100

77101
/**

ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,38 @@ module Public {
127127
SummaryComponentStack return(ReturnKind rk) { result = singleton(SummaryComponent::return(rk)) }
128128
}
129129

130+
private predicate noComponentSpecificCsv(SummaryComponent sc) {
131+
not exists(getComponentSpecificCsv(sc))
132+
}
133+
134+
/** Gets a textual representation of this component used for flow summaries */
135+
private string getComponentCsv(SummaryComponent sc) {
136+
result = getComponentSpecificCsv(sc)
137+
or
138+
noComponentSpecificCsv(sc) and
139+
(
140+
exists(int i | sc = TParameterSummaryComponent(i) and result = "Parameter[" + i + "]")
141+
or
142+
exists(int i | sc = TArgumentSummaryComponent(i) and result = "Argument[" + i + "]")
143+
or
144+
sc = TReturnSummaryComponent(getReturnValueKind()) and result = "ReturnValue"
145+
)
146+
}
147+
148+
/** Gets a textual representation of this stack used for flow summaries. */
149+
string getComponentStackCsv(SummaryComponentStack stack) {
150+
exists(SummaryComponent head, SummaryComponentStack tail |
151+
head = stack.head() and
152+
tail = stack.tail() and
153+
result = getComponentCsv(head) + " of " + getComponentStackCsv(tail)
154+
)
155+
or
156+
exists(SummaryComponent c |
157+
stack = TSingletonSummaryComponentStack(c) and
158+
result = getComponentCsv(c)
159+
)
160+
}
161+
130162
/**
131163
* A class that exists for QL technical reasons only (the IPA type used
132164
* to represent component stacks needs to be bounded).
@@ -970,18 +1002,31 @@ module Private {
9701002
module TestOutput {
9711003
/** A flow summary to include in the `summary/3` query predicate. */
9721004
abstract class RelevantSummarizedCallable extends SummarizedCallable {
973-
/** Gets the string representation of this callable used by `summary/3`. */
974-
string getFullString() { result = this.toString() }
1005+
/** Gets the string representation of this callable used by `summary/1`. */
1006+
abstract string getCallableCsv();
9751007
}
9761008

977-
/** A query predicate for outputting flow summaries in QL tests. */
978-
query predicate summary(string callable, string flow, boolean preservesValue) {
1009+
/** Render the kind in the format used in flow summaries. */
1010+
private string renderKind(boolean preservesValue) {
1011+
preservesValue = true and result = "value"
1012+
or
1013+
preservesValue = false and result = "taint"
1014+
}
1015+
1016+
/**
1017+
* A query predicate for outputting flow summaries in semi-colon separated format in QL tests.
1018+
* The syntax is: "namespace;type;overrides;name;signature;ext;inputspec;outputspec;kind",
1019+
* ext is hardcoded to empty
1020+
*/
1021+
query predicate summary(string csv) {
9791022
exists(
980-
RelevantSummarizedCallable c, SummaryComponentStack input, SummaryComponentStack output
1023+
RelevantSummarizedCallable c, SummaryComponentStack input, SummaryComponentStack output,
1024+
boolean preservesValue
9811025
|
982-
callable = c.getFullString() and
9831026
c.propagatesFlow(input, output, preservesValue) and
984-
flow = input + " -> " + output
1027+
csv =
1028+
c.getCallableCsv() + ";;" + getComponentStackCsv(input) + ";" +
1029+
getComponentStackCsv(output) + ";" + renderKind(preservesValue)
9851030
)
9861031
}
9871032
}

ruby/ql/lib/codeql/ruby/dataflow/internal/FlowSummaryImplSpecific.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ SummaryComponent interpretComponentSpecific(string c) {
6969
result = FlowSummary::SummaryComponent::argument(any(int i | i >= 0))
7070
}
7171

72+
/** Gets the textual representation of a summary component in the format used for flow summaries */
73+
string getComponentSpecificCsv(SummaryComponent sc) {
74+
sc = TArgumentSummaryComponent(-2) and result = "BlockArgument"
75+
}
76+
7277
/** Gets the return kind corresponding to specification `"ReturnValue"`. */
7378
NormalReturnKind getReturnValueKind() { any() }
7479

0 commit comments

Comments
 (0)