Skip to content

JS: Make the edges of API-graphs into IPA types #7180

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

Merged
merged 8 commits into from
Dec 1, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
412 changes: 275 additions & 137 deletions javascript/ql/lib/semmle/javascript/ApiGraphs.qll

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion javascript/ql/lib/semmle/javascript/frameworks/D3.qll
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ module D3 {
or
result = API::moduleImport("d3-node").getInstance().getMember("d3")
or
result = API::root().getASuccessor(any(D3GlobalEntry i))
result = any(D3GlobalEntry i).getNode()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module History {
* Gets a reference to the [`history`](https://npmjs.org/package/history) library.
*/
private API::Node history() {
result = [API::moduleImport("history"), API::root().getASuccessor(any(HistoryGlobalEntry h))]
result = [API::moduleImport("history"), any(HistoryGlobalEntry h).getNode()]
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ private module Immutable {
API::Node immutableImport() {
result = API::moduleImport("immutable")
or
result = API::root().getASuccessor(any(ImmutableGlobalEntry i))
result = any(ImmutableGlobalEntry i).getNode()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ private module Console {
*/
private API::Node console() {
result = API::moduleImport("console") or
result = API::root().getASuccessor(any(ConsoleGlobalEntry e))
result = any(ConsoleGlobalEntry e).getNode()
}

/**
Expand Down
2 changes: 1 addition & 1 deletion javascript/ql/lib/semmle/javascript/frameworks/Nest.qll
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ module NestJS {
private API::Node validationPipe() {
result = nestjs().getMember("ValidationPipe")
or
result = API::root().getASuccessor(any(ValidationNodeEntry e))
result = any(ValidationNodeEntry e).getNode()
}

/**
Expand Down
4 changes: 1 addition & 3 deletions javascript/ql/lib/semmle/javascript/frameworks/Redux.qll
Original file line number Diff line number Diff line change
Expand Up @@ -1111,9 +1111,7 @@ module Redux {

/** A heuristic call to `connect`, recognized by it taking arguments named `mapStateToProps` and `mapDispatchToProps`. */
private class HeuristicConnectFunction extends ConnectCall {
HeuristicConnectFunction() {
this = API::root().getASuccessor(any(HeuristicConnectEntryPoint e)).getACall()
}
HeuristicConnectFunction() { this = any(HeuristicConnectEntryPoint e).getNode().getACall() }

override API::Node getMapStateToProps() {
result = getAParameter() and
Expand Down
4 changes: 2 additions & 2 deletions javascript/ql/lib/semmle/javascript/frameworks/Vue.qll
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module Vue {
API::Node vueLibrary() {
result = API::moduleImport("vue")
or
result = API::root().getASuccessor(any(GlobalVueEntryPoint e))
result = any(GlobalVueEntryPoint e).getNode()
}

/**
Expand All @@ -51,7 +51,7 @@ module Vue {
or
result = vueLibrary().getMember("component").getReturn()
or
result = API::root().getASuccessor(any(VueFileImportEntryPoint e))
result = any(VueFileImportEntryPoint e).getNode()
}

/**
Expand Down
37 changes: 37 additions & 0 deletions javascript/ql/lib/semmle/javascript/internal/CachedStages.qll
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,43 @@ module Stages {
}
}

/**
* The `APIStage` stage.
*/
cached
module APIStage {
/**
* Always holds.
* Ensures that a predicate is evaluated as part of the APIStage stage.
*/
cached
predicate ref() { 1 = 1 }

/**
* DONT USE!
* Contains references to each predicate that use the above `ref` predicate.
*/
cached
predicate backref() {
1 = 1
or
exists(
API::moduleImport("foo")
.getMember("bar")
.getUnknownMember()
.getAMember()
.getAParameter()
.getPromised()
.getReturn()
.getParameter(2)
.getUnknownMember()
.getInstance()
.getReceiver()
.getPromisedError()
)
}
}

/**
* The `taint` stage.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,11 +211,9 @@ module ExternalAPIUsedWithUntrustedData {
node = getNamedParameter(base.getAParameter(), paramName) and
result = basename + ".[callback].[param '" + paramName + "']"
or
exists(string callbackName, string index |
node =
getNamedParameter(base.getASuccessor("parameter " + index).getMember(callbackName),
paramName) and
index != "-1" and // ignore receiver
exists(string callbackName, int index |
node = getNamedParameter(base.getParameter(index).getMember(callbackName), paramName) and
index != -1 and // ignore receiver
result =
basename + ".[callback " + index + " '" + callbackName + "'].[param '" + paramName +
"']"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,23 @@ private class RemoteFlowSourceAccessPath extends JSONString {
string getSourceType() { result = sourceType }

/** Gets the `i`th component of the access path specifying this remote flow source. */
string getComponent(int i) {
API::ApiLabel getComponent(int i) {
exists(string raw | raw = this.getValue().splitAt(".", i + 1) |
i = 0 and
result = "ExternalRemoteFlowSourceSpec " + raw
result
.(API::EdgeLabel::LabelEntryPoint)
.getEntryPoint()
.(ExternalRemoteFlowSourceSpecEntryPoint)
.getName() = raw
or
i > 0 and
result = API::EdgeLabel::member(raw)
)
}

/** Gets the first part of this access path. E.g. for "window.user.name" the result is "window". */
string getRootPath() { result = this.getValue().splitAt(".", 1) }

/** Gets the index of the last component of this access path. */
int getMaxComponentIndex() { result = max(int i | exists(getComponent(i))) }

Expand Down Expand Up @@ -154,10 +161,12 @@ private class ExternalRemoteFlowSourceSpecEntryPoint extends API::EntryPoint {
string name;

ExternalRemoteFlowSourceSpecEntryPoint() {
this = any(RemoteFlowSourceAccessPath s).getComponent(0) and
name = any(RemoteFlowSourceAccessPath s).getRootPath() and
this = "ExternalRemoteFlowSourceSpec " + name
}

string getName() { result = name }

override DataFlow::SourceNode getAUse() { result = DataFlow::globalVarRef(name) }

override DataFlow::Node getARhs() { none() }
Expand Down
2 changes: 1 addition & 1 deletion javascript/ql/src/meta/ApiGraphs/ApiGraphEdges.ql
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ import javascript
import meta.MetaMetrics

select projectRoot(),
count(API::Node pred, string lbl, API::Node succ | succ = pred.getASuccessor(lbl))
count(API::Node pred, API::ApiLabel lbl, API::Node succ | succ = pred.getASuccessor(lbl))
9 changes: 7 additions & 2 deletions javascript/ql/test/ApiGraphs/VerifyAssertions.qll
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ class Assertion extends Comment {
i = getPathLength() and
result = API::root()
or
result = lookup(i + 1).getASuccessor(getEdgeLabel(i))
result =
lookup(i + 1).getASuccessor(any(API::ApiLabel label | label.toString() = getEdgeLabel(i)))
}

predicate isNegative() { polarity = "!" }
Expand All @@ -79,7 +80,11 @@ class Assertion extends Comment {
then
suffix =
"it does have outgoing edges labelled " +
concat(string lbl | exists(nd.getASuccessor(lbl)) | lbl, ", ") + "."
concat(string lbl |
exists(nd.getASuccessor(any(API::ApiLabel label | label.toString() = lbl)))
|
lbl, ", "
) + "."
else suffix = "it has no outgoing edges at all."
|
result = prefix + " " + suffix
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy