|
10 | 10 | */ |
11 | 11 |
|
12 | 12 | import javascript |
| 13 | +private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps |
13 | 14 |
|
14 | 15 | /** |
15 | 16 | * Provides classes and predicates for working with APIs defined or used in a database. |
@@ -747,6 +748,18 @@ module API { |
747 | 748 | result = DataFlow::moduleVarNode(imp.getImportedModule()).getAPropertyRead("exports") |
748 | 749 | ) |
749 | 750 | or |
| 751 | + exists(ObjectExpr obj | |
| 752 | + obj = trackDefNode(nd, t.continue()).asExpr() and |
| 753 | + result = |
| 754 | + obj.getAProperty() |
| 755 | + .(SpreadProperty) |
| 756 | + .getInit() |
| 757 | + .(SpreadElement) |
| 758 | + .getOperand() |
| 759 | + .flow() |
| 760 | + .getALocalSource() |
| 761 | + ) |
| 762 | + or |
750 | 763 | t = defStep(nd, result) |
751 | 764 | } |
752 | 765 |
|
@@ -930,16 +943,38 @@ private module Label { |
930 | 943 | /** Gets the `member` edge label for the unknown member. */ |
931 | 944 | string unknownMember() { result = "member *" } |
932 | 945 |
|
| 946 | + /** |
| 947 | + * Gets a property name referred to by the given dynamic property access, |
| 948 | + * allowing one property flow step in the process (to allow flow through imports). |
| 949 | + * |
| 950 | + * This is to support code patterns where the property name is actually constant, |
| 951 | + * but the property name has been factored into a library. |
| 952 | + */ |
| 953 | + private string getAnIndirectPropName(DataFlow::PropRef ref) { |
| 954 | + exists(DataFlow::Node pred | |
| 955 | + FlowSteps::propertyFlowStep(pred, ref.getPropertyNameExpr().flow()) and |
| 956 | + result = pred.getStringValue() |
| 957 | + ) |
| 958 | + } |
| 959 | + |
| 960 | + /** |
| 961 | + * Gets unique result of `getAnIndirectPropName` if there is one. |
| 962 | + */ |
| 963 | + private string getIndirectPropName(DataFlow::PropRef ref) { |
| 964 | + result = unique(string s | s = getAnIndirectPropName(ref)) |
| 965 | + } |
| 966 | + |
933 | 967 | /** Gets the `member` edge label for the given property reference. */ |
934 | 968 | string memberFromRef(DataFlow::PropRef pr) { |
935 | | - exists(string pn | pn = pr.getPropertyName() | |
| 969 | + exists(string pn | pn = pr.getPropertyName() or pn = getIndirectPropName(pr) | |
936 | 970 | result = member(pn) and |
937 | 971 | // only consider properties with alphanumeric(-ish) names, excluding special properties |
938 | 972 | // and properties whose names look like they are meant to be internal |
939 | 973 | pn.regexpMatch("(?!prototype$|__)[\\w_$][\\w\\-.$]*") |
940 | 974 | ) |
941 | 975 | or |
942 | 976 | not exists(pr.getPropertyName()) and |
| 977 | + not exists(getIndirectPropName(pr)) and |
943 | 978 | result = unknownMember() |
944 | 979 | } |
945 | 980 |
|
|
0 commit comments