Skip to content

Commit ab74898

Browse files
committed
JS: Deprecate getUnknownMember() and replace its uses with getArrayElement()
Although they mean slightly different things, every single call site of getUnknownMember() just used it as a way to get array elements. Since there is no known use-case for the original meaning of getUnknownMember() I am deprecating it for now.
1 parent 4c1c0b7 commit ab74898

File tree

9 files changed

+28
-25
lines changed

9 files changed

+28
-25
lines changed

javascript/ql/lib/semmle/javascript/ApiGraphs.qll

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
1010
private import semmle.javascript.dataflow.internal.PreCallGraphStep
1111
private import semmle.javascript.dataflow.internal.StepSummary
1212
private import semmle.javascript.dataflow.internal.sharedlib.SummaryTypeTracker as SummaryTypeTracker
13+
private import semmle.javascript.dataflow.internal.Contents::Private as ContentPrivate
1314
private import internal.CachedStages
1415

1516
/**
@@ -222,13 +223,17 @@ module API {
222223
}
223224

224225
/**
225-
* Gets a node representing a member of this API component where the name of the member is
226-
* not known statically.
226+
* DEPRECATED. Use either `getArrayElement()` or `getAMember()` instead.
227+
*/
228+
deprecated Node getUnknownMember() { result = this.getArrayElement() }
229+
230+
/**
231+
* Gets an array element of unknown index.
227232
*/
228233
cached
229-
Node getUnknownMember() {
234+
Node getUnknownArrayElement() {
230235
Stages::ApiStage::ref() and
231-
result = this.getASuccessor(Label::unknownMember())
236+
result = this.getASuccessor(Label::content(ContentPrivate::MkArrayElementUnknown()))
232237
}
233238

234239
cached
@@ -274,7 +279,7 @@ module API {
274279
Stages::ApiStage::ref() and
275280
result = this.getMember(_)
276281
or
277-
result = this.getUnknownMember()
282+
result = this.getUnknownArrayElement()
278283
}
279284

280285
/**
@@ -1505,7 +1510,12 @@ module API {
15051510
/** Gets the `content` edge label for content `c`. */
15061511
LabelContent content(ContentPrivate::Content c) { result.getContent() = c }
15071512

1508-
/** Gets the `member` edge label for the unknown member. */
1513+
/**
1514+
* Gets the edge label for an unknown member.
1515+
*
1516+
* Currently this is represented the same way as an unknown array element, but this may
1517+
* change in the future.
1518+
*/
15091519
LabelContent unknownMember() { result.getContent().isUnknownArrayElement() }
15101520

15111521
/**
@@ -1580,7 +1590,6 @@ module API {
15801590
/** Gets an entry-point label for the entry-point `e`. */
15811591
LabelEntryPoint entryPoint(API::EntryPoint e) { result.getEntryPoint() = e }
15821592

1583-
private import semmle.javascript.dataflow.internal.Contents::Private as ContentPrivate
15841593
private import LabelImpl
15851594

15861595
private module LabelImpl {
@@ -1676,7 +1685,7 @@ module API {
16761685
or
16771686
content instanceof ContentPrivate::MkPromiseError and result = "getPromisedError()"
16781687
or
1679-
content instanceof ContentPrivate::MkArrayElementUnknown and result = "getUnknownMember()"
1688+
content instanceof ContentPrivate::MkArrayElementUnknown and result = "getArrayElement()"
16801689
}
16811690

16821691
override string toString() {

javascript/ql/lib/semmle/javascript/frameworks/D3.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ module D3 {
8080
or
8181
this = d3Selection().getMember("node").getReturn().asSource()
8282
or
83-
this = d3Selection().getMember("nodes").getReturn().getUnknownMember().asSource()
83+
this = d3Selection().getMember("nodes").getReturn().getArrayElement().asSource()
8484
}
8585
}
8686

javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ module Puppeteer {
3232
or
3333
result = [browser(), context()].getMember("newPage").getReturn().getPromised()
3434
or
35-
result = [browser(), context()].getMember("pages").getReturn().getPromised().getUnknownMember()
35+
result = [browser(), context()].getMember("pages").getReturn().getPromised().getArrayElement()
3636
or
3737
result = target().getMember("page").getReturn().getPromised()
3838
}
@@ -45,7 +45,7 @@ module Puppeteer {
4545
or
4646
result = [page(), browser()].getMember("target").getReturn()
4747
or
48-
result = context().getMember("targets").getReturn().getUnknownMember()
48+
result = context().getMember("targets").getReturn().getArrayElement()
4949
or
5050
result = target().getMember("opener").getReturn()
5151
}
@@ -58,7 +58,7 @@ module Puppeteer {
5858
or
5959
result = [page(), target()].getMember("browserContext").getReturn()
6060
or
61-
result = browser().getMember("browserContexts").getReturn().getUnknownMember()
61+
result = browser().getMember("browserContexts").getReturn().getArrayElement()
6262
or
6363
result = browser().getMember("createIncognitoBrowserContext").getReturn().getPromised()
6464
or

javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,7 @@ module Vuex {
104104
storeName = this.getNamespace() + localName
105105
or
106106
// mapGetters(['foo', 'bar'])
107-
this.getLastParameter().getUnknownMember().getAValueReachingSink().getStringValue() =
108-
localName and
107+
this.getLastParameter().getArrayElement().getAValueReachingSink().getStringValue() = localName and
109108
storeName = this.getNamespace() + localName
110109
or
111110
// mapGetters({foo: 'bar'})

javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ bindingset[pred]
368368
predicate apiGraphHasEdge(API::Node pred, string path, API::Node succ) {
369369
exists(string name | succ = pred.getMember(name) and path = "Member[" + name + "]")
370370
or
371-
succ = pred.getUnknownMember() and path = "AnyMember"
371+
succ = pred.getUnknownArrayElement() and path = "ArrayElement"
372372
or
373373
succ = pred.getInstance() and path = "Instance"
374374
or

javascript/ql/lib/semmle/javascript/internal/CachedStages.qll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,13 +297,12 @@ module Stages {
297297
exists(
298298
API::moduleImport("foo")
299299
.getMember("bar")
300-
.getUnknownMember()
300+
.getArrayElement()
301301
.getAMember()
302302
.getAParameter()
303303
.getPromised()
304304
.getReturn()
305305
.getParameter(2)
306-
.getUnknownMember()
307306
.getInstance()
308307
.getReceiver()
309308
.getForwardingFunction()

javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@ module ExternalApiUsedWithUntrustedData {
179179
or
180180
exists(string member |
181181
node = base.getMember(member) and
182-
not node = base.getUnknownMember() and
183182
not isNumericString(member) and
184183
not (member = "default" and base = API::moduleImport(_)) and
185184
not member = "then" // use the 'promised' edges for .then callbacks
@@ -189,10 +188,7 @@ module ExternalApiUsedWithUntrustedData {
189188
else result = basename + "['" + member.regexpReplaceAll("'", "\\'") + "']"
190189
)
191190
or
192-
(
193-
node = base.getUnknownMember() or
194-
node = base.getMember(any(string s | isNumericString(s)))
195-
) and
191+
node = base.getArrayElement() and
196192
result = basename + "[]"
197193
or
198194
// just collapse promises

javascript/ql/src/experimental/Security/CWE-347/JWT.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ DataFlow::Node unverifiedDecode() {
77
verify
88
.getParameter(2)
99
.getMember("algorithms")
10-
.getUnknownMember()
10+
.getArrayElement()
1111
.asSink()
1212
.mayHaveStringValue("none") and
1313
result = verify.getParameter(0).asSink()
@@ -32,7 +32,7 @@ DataFlow::Node verifiedDecode() {
3232
not verify
3333
.getParameter(2)
3434
.getMember("algorithms")
35-
.getUnknownMember()
35+
.getArrayElement()
3636
.asSink()
3737
.mayHaveStringValue("none") or
3838
not exists(verify.getParameter(2).getMember("algorithms"))

javascript/ql/src/experimental/semmle/javascript/Execa.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ module Execa {
7272
override predicate isShellInterpreted(DataFlow::Node arg) {
7373
// if shell: true then first and second args are sinks
7474
// options can be third argument
75-
arg = [this.getArgument(0), this.getParameter(1).getUnknownMember().asSink()] and
75+
arg = [this.getArgument(0), this.getParameter(1).getArrayElement().asSink()] and
7676
isExecaShellEnable(this.getParameter(2))
7777
or
7878
// options can be second argument

0 commit comments

Comments
 (0)