Skip to content

Commit fefe30a

Browse files
committed
JS: Add API graph edges for indirect propref members
1 parent 2a3bc0f commit fefe30a

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

javascript/ql/src/semmle/javascript/ApiGraphs.qll

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*/
1111

1212
import javascript
13+
private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps
1314

1415
/**
1516
* Provides classes and predicates for working with APIs defined or used in a database.
@@ -945,16 +946,38 @@ private module Label {
945946
/** Gets the `member` edge label for the unknown member. */
946947
string unknownMember() { result = "member *" }
947948

949+
/**
950+
* Gets a property name referred to by the given dynamic property access,
951+
* allowing one property flow step in the process (to allow flow through imports).
952+
*
953+
* This is to support code patterns where the property name is actually constant,
954+
* but the property name has been factored into a library.
955+
*/
956+
private string getAnIndirectPropName(DataFlow::PropRef ref) {
957+
exists(DataFlow::Node pred |
958+
FlowSteps::propertyFlowStep(pred, ref.getPropertyNameExpr().flow()) and
959+
result = pred.getStringValue()
960+
)
961+
}
962+
963+
/**
964+
* Gets unique result of `getAnIndirectPropName` if there is one.
965+
*/
966+
private string getIndirectPropName(DataFlow::PropRef ref) {
967+
result = unique(string s | s = getAnIndirectPropName(ref))
968+
}
969+
948970
/** Gets the `member` edge label for the given property reference. */
949971
string memberFromRef(DataFlow::PropRef pr) {
950-
exists(string pn | pn = pr.getPropertyName() |
972+
exists(string pn | pn = pr.getPropertyName() or pn = getIndirectPropName(pr) |
951973
result = member(pn) and
952974
// only consider properties with alphanumeric(-ish) names, excluding special properties
953975
// and properties whose names look like they are meant to be internal
954976
pn.regexpMatch("(?!prototype$|__)[\\w_$][\\w\\-.$]*")
955977
)
956978
or
957979
not exists(pr.getPropertyName()) and
980+
not exists(getIndirectPropName(pr)) and
958981
result = unknownMember()
959982
}
960983

0 commit comments

Comments
 (0)