Skip to content

Commit daabd3a

Browse files
authored
Merge pull request #673 from owen-mc/refactor-returnvalue-n
Refactor `ReturnValue[n]` in data flow libraries
2 parents d6d1c94 + 44641de commit daabd3a

2 files changed

Lines changed: 54 additions & 36 deletions

File tree

ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 11 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -822,32 +822,14 @@ module Private {
822822
)
823823
}
824824

825-
/** Holds if specification component `c` parses as return value `n`. */
826-
predicate parseReturn(string c, int n) {
827-
specSplit(_, c, _) and
828-
(
829-
c = "ReturnValue" and n = 0
830-
or
831-
c.regexpCapture("ReturnValue\\[([-0-9]+)\\]", 1).toInt() = n
832-
or
833-
exists(int n1, int n2 |
834-
c.regexpCapture("ReturnValue\\[([-0-9]+)\\.\\.([0-9]+)\\]", 1).toInt() = n1 and
835-
c.regexpCapture("ReturnValue\\[([-0-9]+)\\.\\.([0-9]+)\\]", 2).toInt() = n2 and
836-
n = [n1 .. n2]
837-
)
838-
)
839-
}
840-
841825
private SummaryComponent interpretComponent(string c) {
842826
specSplit(_, c, _) and
843827
(
844828
exists(int pos | parseArg(c, pos) and result = SummaryComponent::argument(pos))
845829
or
846830
exists(int pos | parseParam(c, pos) and result = SummaryComponent::parameter(pos))
847831
or
848-
exists(int pos |
849-
parseReturn(c, pos) and result = SummaryComponent::return(getReturnKind(pos))
850-
)
832+
c = "ReturnValue" and result = SummaryComponent::return(getReturnValueKind())
851833
or
852834
result = interpretComponentSpecific(c)
853835
)
@@ -914,12 +896,15 @@ module Private {
914896
not exists(interpretComponent(c))
915897
}
916898

917-
private predicate inputNeedsReference(string c) { parseArg(c, _) }
899+
private predicate inputNeedsReference(string c) {
900+
parseArg(c, _) or
901+
inputNeedsReferenceSpecific(c)
902+
}
918903

919904
private predicate outputNeedsReference(string c) {
920905
parseArg(c, _) or
921906
c = "ReturnValue" or
922-
parseReturn(c, _)
907+
outputNeedsReferenceSpecific(c)
923908
}
924909

925910
private predicate sourceElementRef(InterpretNode ref, string output, string kind) {
@@ -959,13 +944,8 @@ module Private {
959944
c = "Parameter" or parseParam(c, pos)
960945
)
961946
or
962-
exists(int pos |
963-
node.asNode() = getAnOutNodeExt(mid.asCall(), TValueReturn(getReturnKind(pos)))
964-
|
965-
c = "ReturnValue" and pos = 0
966-
or
967-
parseReturn(c, pos)
968-
)
947+
c = "ReturnValue" and
948+
node.asNode() = getAnOutNodeExt(mid.asCall(), TValueReturn(getReturnValueKind()))
969949
or
970950
interpretOutputSpecific(c, mid, node)
971951
)
@@ -982,14 +962,10 @@ module Private {
982962
|
983963
exists(int pos | node.asNode().(ArgNode).argumentOf(mid.asCall(), pos) | parseArg(c, pos))
984964
or
985-
exists(int pos, ReturnNodeExt ret |
986-
(
987-
c = "ReturnValue" and pos = 0
988-
or
989-
parseReturn(c, pos)
990-
) and
965+
exists(ReturnNodeExt ret |
966+
c = "ReturnValue" and
991967
ret = node.asNode() and
992-
ret.getKind().(ValueReturnKind).getKind() = getReturnKind(pos) and
968+
ret.getKind().(ValueReturnKind).getKind() = getReturnValueKind() and
993969
mid.asCallable() = getNodeEnclosingCallable(ret)
994970
)
995971
or

ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ private import DataFlowUtil
88
private import FlowSummaryImpl::Private
99
private import FlowSummaryImpl::Public
1010
private import semmle.go.dataflow.ExternalFlow
11+
private import DataFlowImplCommon
1112

1213
private module FlowSummaries {
1314
private import semmle.go.dataflow.FlowSummary as F
@@ -65,6 +66,8 @@ predicate summaryElement(DataFlowCallable c, string input, string output, string
6566
/** Gets the summary component for specification component `c`, if any. */
6667
bindingset[c]
6768
SummaryComponent interpretComponentSpecific(string c) {
69+
exists(int pos | parseReturn(c, pos) and result = SummaryComponent::return(getReturnKind(pos)))
70+
or
6871
exists(Content content | parseContent(c, content) and result = SummaryComponent::content(content))
6972
}
7073

@@ -92,8 +95,20 @@ private string getContentSpecificCsv(Content c) {
9295
/** Gets the textual representation of the content in the format used for flow summaries. */
9396
string getComponentSpecificCsv(SummaryComponent sc) {
9497
exists(Content c | sc = TContentSummaryComponent(c) and result = getContentSpecificCsv(c))
98+
or
99+
exists(ReturnKind rk, int n | n = rk.getIndex() |
100+
sc = TReturnSummaryComponent(rk) and
101+
result = "ReturnValue[" + n + "]" and
102+
n != 0
103+
)
95104
}
96105

106+
/** Holds if input specification component `c` needs a reference. */
107+
predicate inputNeedsReferenceSpecific(string c) { none() }
108+
109+
/** Holds if output specification component `c` needs a reference. */
110+
predicate outputNeedsReferenceSpecific(string c) { parseReturn(c, _) }
111+
97112
private newtype TSourceOrSinkElement =
98113
TEntityElement(Entity e) or
99114
TAstElement(AstNode n)
@@ -144,7 +159,7 @@ predicate sinkElement(SourceOrSinkElement e, string input, string kind) {
144159
}
145160

146161
/** Gets the return kind corresponding to specification `"ReturnValue"`. */
147-
ReturnKind getReturnValueKind() { any() }
162+
ReturnKind getReturnValueKind() { result = getReturnKind(0) }
148163

149164
private newtype TInterpretNode =
150165
TElement(SourceOrSinkElement n) or
@@ -191,6 +206,10 @@ class InterpretNode extends TInterpretNode {
191206
/** Provides additional sink specification logic required for annotations. */
192207
pragma[inline]
193208
predicate interpretOutputSpecific(string c, InterpretNode mid, InterpretNode node) {
209+
exists(int pos | node.asNode() = getAnOutNodeExt(mid.asCall(), TValueReturn(getReturnKind(pos))) |
210+
parseReturn(c, pos)
211+
)
212+
or
194213
exists(Node n, SourceOrSinkElement e |
195214
n = node.asNode() and
196215
e = mid.asElement()
@@ -206,9 +225,32 @@ predicate interpretOutputSpecific(string c, InterpretNode mid, InterpretNode nod
206225
/** Provides additional source specification logic required for annotations. */
207226
pragma[inline]
208227
predicate interpretInputSpecific(string c, InterpretNode mid, InterpretNode n) {
228+
exists(int pos, ReturnNodeExt ret |
229+
parseReturn(c, pos) and
230+
ret = n.asNode() and
231+
ret.getKind().(ValueReturnKind).getKind() = getReturnKind(pos) and
232+
mid.asCallable() = getNodeEnclosingCallable(ret)
233+
)
234+
or
209235
exists(DataFlow::Write fw, Field f |
210236
c = "" and
211237
f = mid.asElement().asEntity() and
212238
fw.writesField(_, f, n.asNode())
213239
)
214240
}
241+
242+
/** Holds if specification component `c` parses as return value `n`. */
243+
predicate parseReturn(string c, int n) {
244+
External::specSplit(_, c, _) and
245+
(
246+
c = "ReturnValue" and n = 0
247+
or
248+
c.regexpCapture("ReturnValue\\[([-0-9]+)\\]", 1).toInt() = n
249+
or
250+
exists(int n1, int n2 |
251+
c.regexpCapture("ReturnValue\\[([-0-9]+)\\.\\.([0-9]+)\\]", 1).toInt() = n1 and
252+
c.regexpCapture("ReturnValue\\[([-0-9]+)\\.\\.([0-9]+)\\]", 2).toInt() = n2 and
253+
n = [n1 .. n2]
254+
)
255+
)
256+
}

0 commit comments

Comments
 (0)