Skip to content

Commit f475bb1

Browse files
committed
JS: Add missing flow steps.
1 parent d8037fa commit f475bb1

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

‎javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,43 @@ module NodeJSLib {
921921
overlay[local?]
922922
private predicate isWriteHook(string name) { name = "_write" }
923923

924+
overlay[local?]
925+
private predicate builtinStreamCreation(NewExpr creation, string kind) {
926+
exists(EarlyStageNode constructor |
927+
kind = ["Writable", "Duplex", "Transform"] and
928+
memberRead(getAStreamModuleNode(), kind, constructor) and
929+
DataFlow::localFlowStep*(constructor, TValueNode(creation.getCallee())) and
930+
not creation.getTopLevel().isExterns()
931+
)
932+
}
933+
934+
overlay[local?]
935+
private Expr streamOptionValue(NewExpr creation, string name) {
936+
exists(ObjectExpr options |
937+
DataFlow::localFlowStep*(TValueNode(options), TValueNode(creation.getArgument(0))) and
938+
result = options.getPropertyByName(name).getInit()
939+
)
940+
}
941+
942+
overlay[local?]
943+
private predicate hasStreamWriteOption(NewExpr creation) {
944+
DataFlow::localFlowStep*(TValueNode(any(Function callback)),
945+
TValueNode(streamOptionValue(creation, "write")))
946+
}
947+
948+
overlay[local?]
949+
private class StreamConstructorHookStep extends PreCallGraphStep {
950+
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
951+
exists(PipeCall pipe, NewExpr creation, string name |
952+
builtinStreamCreation(creation, _) and
953+
DataFlow::localFlowStep*(TValueNode(creation), TValueNode(pipe.getArgument(0))) and
954+
name = ["write", "transform"] and
955+
pred = streamOptionValue(creation, name).flow() and
956+
succ = getSynthesizedNode(pipe, pipeHookTag("_" + name, "member"))
957+
)
958+
}
959+
}
960+
924961
overlay[local?]
925962
private ClassDefinition instantiatedClassWithoutWriteOverride(NewExpr creation) {
926963
DataFlow::localFlowStep*(TValueNode(result), TValueNode(creation.getCallee())) and
@@ -950,6 +987,20 @@ module NodeJSLib {
950987
then hook = "_transform"
951988
else hook = "_write"
952989
)
990+
or
991+
exists(NewExpr creation, string kind |
992+
builtinStreamCreation(creation, kind) and
993+
creation = pipeDestinationWithoutWriteOverride(pipe)
994+
|
995+
kind = ["Writable", "Duplex"] and hook = "_write"
996+
or
997+
kind = "Transform" and
998+
if
999+
hasStreamWriteOption(creation) or
1000+
StreamMethodOverride<isWriteHook/1>::overridesStreamInstanceMethod(creation)
1001+
then hook = "_write"
1002+
else hook = "_transform"
1003+
)
9531004
}
9541005

9551006
overlay[local?]

0 commit comments

Comments
 (0)