@@ -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