Skip to content

Commit 623531a

Browse files
authored
Merge pull request #10206 from asgerf/js/js-mad-changes
JS: Some JS-specific MaD changes
2 parents f5d43b8 + f589520 commit 623531a

File tree

6 files changed

+61
-8
lines changed

6 files changed

+61
-8
lines changed

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,9 @@ module API {
533533

534534
/** Gets a node corresponding to an import of module `m`. */
535535
Node moduleImport(string m) {
536-
result = Impl::MkModuleImport(m) or
537-
result = Impl::MkModuleImport(m).(Node).getMember("default")
536+
result = Internal::getAModuleImportRaw(m)
537+
or
538+
result = ModelOutput::getATypeNode(m, "")
538539
}
539540

540541
/** Gets a node corresponding to an export of module `m`. */
@@ -544,6 +545,22 @@ module API {
544545
module Node {
545546
/** Gets a node whose type has the given qualified name. */
546547
Node ofType(string moduleName, string exportedName) {
548+
result = Internal::getANodeOfTypeRaw(moduleName, exportedName)
549+
or
550+
result = ModelOutput::getATypeNode(moduleName, exportedName)
551+
}
552+
}
553+
554+
/** Provides access to API graph nodes without taking into account types from models. */
555+
module Internal {
556+
/** Gets a node corresponding to an import of module `m` without taking into account types from models. */
557+
Node getAModuleImportRaw(string m) {
558+
result = Impl::MkModuleImport(m) or
559+
result = Impl::MkModuleImport(m).(Node).getMember("default")
560+
}
561+
562+
/** Gets a node whose type has the given qualified name, not including types from models. */
563+
Node getANodeOfTypeRaw(string moduleName, string exportedName) {
547564
result = Impl::MkTypeUse(moduleName, exportedName).(Node).getInstance()
548565
}
549566
}

javascript/ql/lib/semmle/javascript/Classes.qll

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,9 @@ class MemberDeclaration extends @property, Documentable {
493493
*/
494494
predicate isStatic() { is_static(this) }
495495

496+
/** Gets a boolean indicating if this member is static. */
497+
boolean getStaticAsBool() { if this.isStatic() then result = true else result = false }
498+
496499
/**
497500
* Holds if this member is abstract.
498501
*
@@ -694,10 +697,10 @@ class MethodDeclaration extends MemberDeclaration {
694697
* the overload index is defined as if only one of them was concrete.
695698
*/
696699
int getOverloadIndex() {
697-
exists(ClassOrInterface type, string name |
700+
exists(ClassOrInterface type, string name, boolean static |
698701
this =
699702
rank[result + 1](MethodDeclaration method, int i |
700-
methodDeclaredInType(type, name, i, method)
703+
methodDeclaredInType(type, name, static, i, method)
701704
|
702705
method order by i
703706
)
@@ -718,10 +721,11 @@ class MethodDeclaration extends MemberDeclaration {
718721
* Holds if the `index`th member of `type` is `method`, which has the given `name`.
719722
*/
720723
private predicate methodDeclaredInType(
721-
ClassOrInterface type, string name, int index, MethodDeclaration method
724+
ClassOrInterface type, string name, boolean static, int index, MethodDeclaration method
722725
) {
723726
not method instanceof ConstructorDeclaration and // distinguish methods named "constructor" from the constructor
724727
type.getMemberByIndex(index) = method and
728+
static = method.getStaticAsBool() and
725729
method.getName() = name
726730
}
727731

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

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ API::Node getExtraSuccessorFromNode(API::Node node, AccessPathToken token) {
104104
token.getName() = "Member" and
105105
result = node.getMember(token.getAnArgument())
106106
or
107+
token.getName() = "AnyMember" and
108+
result = node.getAMember()
109+
or
107110
token.getName() = "Instance" and
108111
result = node.getInstance()
109112
or
@@ -163,6 +166,16 @@ predicate invocationMatchesExtraCallSiteFilter(API::InvokeNode invoke, AccessPat
163166
token.getName() = "Call" and
164167
invoke instanceof API::CallNode and
165168
invoke instanceof DataFlow::CallNode // Workaround compiler bug
169+
or
170+
token.getName() = "WithStringArgument" and
171+
exists(string operand, string argIndex, string stringValue |
172+
operand = token.getAnArgument() and
173+
argIndex = operand.splitAt("=", 0) and
174+
stringValue = operand.splitAt("=", 1) and
175+
invoke
176+
.getArgument(AccessPath::parseIntWithArity(argIndex, invoke.getNumArgument()))
177+
.getStringValue() = stringValue
178+
)
166179
}
167180

168181
/**
@@ -225,8 +238,9 @@ bindingset[name]
225238
predicate isExtraValidTokenNameInIdentifyingAccessPath(string name) {
226239
name =
227240
[
228-
"Member", "Instance", "Awaited", "ArrayElement", "Element", "MapValue", "NewCall", "Call",
229-
"DecoratedClass", "DecoratedMember", "DecoratedParameter"
241+
"Member", "AnyMember", "Instance", "Awaited", "ArrayElement", "Element", "MapValue",
242+
"NewCall", "Call", "DecoratedClass", "DecoratedMember", "DecoratedParameter",
243+
"WithStringArgument"
230244
]
231245
}
232246

@@ -237,7 +251,7 @@ predicate isExtraValidTokenNameInIdentifyingAccessPath(string name) {
237251
predicate isExtraValidNoArgumentTokenInIdentifyingAccessPath(string name) {
238252
name =
239253
[
240-
"Instance", "Awaited", "ArrayElement", "Element", "MapValue", "NewCall", "Call",
254+
"AnyMember", "Instance", "Awaited", "ArrayElement", "Element", "MapValue", "NewCall", "Call",
241255
"DecoratedClass", "DecoratedMember", "DecoratedParameter"
242256
]
243257
}
@@ -250,4 +264,8 @@ bindingset[name, argument]
250264
predicate isExtraValidTokenArgumentInIdentifyingAccessPath(string name, string argument) {
251265
name = ["Member"] and
252266
exists(argument)
267+
or
268+
name = "WithStringArgument" and
269+
exists(argument.indexOf("=")) and
270+
exists(AccessPath::parseIntWithArity(argument.splitAt("=", 0), 10))
253271
}

javascript/ql/test/library-tests/frameworks/data/test.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ taintFlow
5555
| test.js:182:12:182:19 | source() | test.js:182:12:182:19 | source() |
5656
| test.js:187:31:187:31 | x | test.js:189:10:189:10 | x |
5757
| test.js:203:32:203:39 | source() | test.js:203:32:203:39 | source() |
58+
| test.js:207:24:207:31 | source() | test.js:207:24:207:31 | source() |
59+
| test.js:208:24:208:31 | source() | test.js:208:24:208:31 | source() |
60+
| test.js:211:34:211:41 | source() | test.js:211:34:211:41 | source() |
5861
isSink
5962
| test.js:54:18:54:25 | source() | test-sink |
6063
| test.js:55:22:55:29 | source() | test-sink |
@@ -113,6 +116,9 @@ isSink
113116
| test.js:182:12:182:19 | source() | test-sink |
114117
| test.js:196:12:196:29 | this._wrappedField | test-sink |
115118
| test.js:203:32:203:39 | source() | test-sink |
119+
| test.js:207:24:207:31 | source() | test-sink |
120+
| test.js:208:24:208:31 | source() | test-sink |
121+
| test.js:211:34:211:41 | source() | test-sink |
116122
syntaxErrors
117123
| Member[foo |
118124
| Member[foo] .Member[bar] |

javascript/ql/test/library-tests/frameworks/data/test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,9 @@ class OtherClass {
203203
this.accessorAroundField = source(); // NOT OK
204204
}
205205
}
206+
207+
testlib.foo.memberSink(source()); // NOT OK
208+
testlib.bar.memberSink(source()); // NOT OK
209+
testlib.memberSink(source()); // OK
210+
testlib.overloadedSink('safe', source()); // OK
211+
testlib.overloadedSink('danger', source()); // NOT OK

javascript/ql/test/library-tests/frameworks/data/test.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class Sinks extends ModelInput::SinkModelCsv {
3838
"testlib;;Member[MethodDecorator].DecoratedMember.ReturnValue;test-sink",
3939
"testlib;;Member[MethodDecoratorWithArgs].ReturnValue.DecoratedMember.ReturnValue;test-sink",
4040
"testlib;;Member[ParamDecoratorSink].DecoratedParameter;test-sink",
41+
"testlib;;AnyMember.Member[memberSink].Argument[0];test-sink",
42+
"testlib;;Member[overloadedSink].WithStringArgument[0=danger].Argument[1];test-sink",
4143
]
4244
}
4345
}

0 commit comments

Comments
 (0)