@@ -16,57 +16,101 @@ private import semmle.python.frameworks.internal.PoorMansFunctionResolution
1616 * See https://python-socketio.readthedocs.io/en/stable/.
1717 */
1818module SocketIO {
19- /** An instance of a socketio `Server` or `AsyncServer`. */
20- API:: Node server ( ) {
21- result = API:: moduleImport ( "socketio" ) .getMember ( [ "Server" , "AsyncServer" ] ) .getAnInstance ( )
22- }
23-
24- API:: Node serverEventAnnotation ( ) {
25- result = server ( ) .getMember ( "event" )
26- or
27- result = server ( ) .getMember ( "on" ) .getReturn ( )
28- }
19+ /** Provides models for socketio `Server` and `AsyncServer` classes. */
20+ module Server {
21+ /** An instance of a socketio `Server` or `AsyncServer`. */
22+ API:: Node server ( ) {
23+ result = API:: moduleImport ( "socketio" ) .getMember ( [ "Server" , "AsyncServer" ] ) .getAnInstance ( )
24+ }
2925
30- private class EventHandler extends Http :: Server :: RequestHandler :: Range {
31- EventHandler ( ) {
32- serverEventAnnotation ( ) . getAValueReachableFromSource ( ) . asExpr ( ) = this . getADecorator ( )
26+ /** A decorator that indicates a socketio event handler. */
27+ private API :: Node serverEventAnnotation ( ) {
28+ result = server ( ) . getMember ( "event" )
3329 or
34- exists ( DataFlow:: CallCfgNode c , DataFlow:: Node arg | c = server ( ) .getMember ( "on" ) .getACall ( ) |
35- (
36- arg = c .getArg ( 1 )
37- or
38- arg = c .getArgByName ( "handler" )
39- ) and
40- poorMansFunctionTracker ( this ) = arg
41- )
30+ result = server ( ) .getMember ( "on" ) .getReturn ( )
31+ }
32+
33+ private class EventHandler extends Http:: Server:: RequestHandler:: Range {
34+ EventHandler ( ) {
35+ serverEventAnnotation ( ) .getAValueReachableFromSource ( ) .asExpr ( ) = this .getADecorator ( )
36+ or
37+ exists ( DataFlow:: CallCfgNode c , DataFlow:: Node arg |
38+ c = server ( ) .getMember ( "on" ) .getACall ( )
39+ |
40+ (
41+ arg = c .getArg ( 1 )
42+ or
43+ arg = c .getArgByName ( "handler" )
44+ ) and
45+ poorMansFunctionTracker ( this ) = arg
46+ )
47+ }
48+
49+ override Parameter getARoutedParameter ( ) {
50+ result = this .getAnArg ( ) and
51+ not result = this .getArg ( 0 ) // First parameter is `sid`, which is not a remote flow source as it cannot be controlled by the client.
52+ }
53+
54+ override string getFramework ( ) { result = "socketio" }
4255 }
4356
44- override Parameter getARoutedParameter ( ) {
45- result = this .getAnArg ( ) and not result = this .getArg ( 0 )
57+ private class CallbackArgument extends DataFlow:: Node {
58+ CallbackArgument ( ) {
59+ exists ( DataFlow:: CallCfgNode c |
60+ c = [ server ( ) , Namespace:: instance ( ) ] .getMember ( [ "emit" , "send" ] ) .getACall ( )
61+ |
62+ this = c .getArgByName ( "callback" )
63+ )
64+ }
4665 }
4766
48- override string getFramework ( ) { result = "socketio" }
49- }
67+ private class CallbackHandler extends Http:: Server:: RequestHandler:: Range {
68+ CallbackHandler ( ) { any ( CallbackArgument ca ) = poorMansFunctionTracker ( this ) }
69+
70+ override Parameter getARoutedParameter ( ) { result = this .getAnArg ( ) }
5071
51- private class CallbackArgument extends DataFlow:: Node {
52- CallbackArgument ( ) {
53- exists ( DataFlow:: CallCfgNode c | c = server ( ) .getMember ( [ "emit" , "send" ] ) .getACall ( ) |
54- this = c .getArgByName ( "callback" )
55- )
72+ override string getFramework ( ) { result = "socketio" }
73+ }
74+
75+ private class SocketIOCall extends RemoteFlowSource:: Range {
76+ SocketIOCall ( ) { this = [ server ( ) , Namespace:: instance ( ) ] .getMember ( "call" ) .getACall ( ) }
77+
78+ override string getSourceType ( ) { result = "socketio call" }
5679 }
5780 }
5881
59- private class CallbackHandler extends Http:: Server:: RequestHandler:: Range {
60- CallbackHandler ( ) { any ( CallbackArgument ca ) = poorMansFunctionTracker ( this ) }
82+ /** Provides modelling for socketio server Namespace/AsyncNamespace classes. */
83+ module Namespace {
84+ /** Gets a reference to the `socketio.Namespace` or `socketio.AsyncNamespace` classes or any subclass. */
85+ API:: Node subclassRef ( ) {
86+ result =
87+ API:: moduleImport ( "socketio" ) .getMember ( [ "Namespace" , "AsyncNamespace" ] ) .getASubclass * ( )
88+ }
6189
62- override Parameter getARoutedParameter ( ) { result = this .getAnArg ( ) }
90+ /** Gets a reference to an instance of a subclass of `socketio.Namespace` or `socketio.AsyncNamespace`. */
91+ API:: Node instance ( ) { result = subclassRef ( ) .getAnInstance ( ) }
6392
64- override string getFramework ( ) { result = "socketio" }
65- }
93+ /** A socketio Namespace class. */
94+ class NamespaceClass extends Class {
95+ NamespaceClass ( ) { this .getABase ( ) = subclassRef ( ) .asSource ( ) .asExpr ( ) }
6696
67- private class SocketIOCall extends RemoteFlowSource:: Range {
68- SocketIOCall ( ) { this = server ( ) .getMember ( "call" ) .getACall ( ) }
97+ /** Gets a handler for socketio events. */
98+ Function getAnEventHandler ( ) {
99+ result = this .getAMethod ( ) and
100+ result .getName ( ) .matches ( "on_%" )
101+ }
102+ }
103+
104+ private class NamespaceEventHandler extends Http:: Server:: RequestHandler:: Range {
105+ NamespaceEventHandler ( ) { this = any ( NamespaceClass nc ) .getAnEventHandler ( ) }
69106
70- override string getSourceType ( ) { result = "socketio call" }
107+ override Parameter getARoutedParameter ( ) {
108+ result = this .getAnArg ( ) and
109+ not result = this .getArg ( 0 ) and
110+ not result = this .getArg ( 1 ) // First 2 parameters are `self` and `sid`.
111+ }
112+
113+ override string getFramework ( ) { result = "socketio" }
114+ }
71115 }
72116}
0 commit comments