11import python
2-
32import semmle.python.types.Builtins
3+ import semmle.python.objects.Callables
44
5- class RecordedCall extends XMLElement {
6- RecordedCall ( ) { this .hasName ( "recorded_call" ) }
5+ class XMLRecordedCall extends XMLElement {
6+ XMLRecordedCall ( ) { this .hasName ( "recorded_call" ) }
77
8- string call_filename ( ) { result = this .getAttributeValue ( "call_filename" ) }
8+ Call getCall ( ) {
9+ result = this .getXMLCall ( ) .getCall ( )
10+ }
911
10- int call_linenum ( ) { result = this .getAttributeValue ( "call_linenum" ) .toInt ( ) }
12+ XMLCall getXMLCall ( ) { result .getParent ( ) = this }
13+
14+ XMLCallee getXMLCallee ( ) { result .getParent ( ) = this }
15+ }
1116
12- int call_inst_index ( ) { result = this .getAttributeValue ( "call_inst_index" ) .toInt ( ) }
17+ class XMLCall extends XMLElement {
18+ XMLCall ( ) { this .hasName ( "Call" ) }
19+
20+ string get_filename_data ( ) { result = this .getAChild ( "filename" ) .getTextValue ( ) }
21+
22+ int get_linenum_data ( ) { result = this .getAChild ( "linenum" ) .getTextValue ( ) .toInt ( ) }
23+
24+ int get_inst_index_data ( ) { result = this .getAChild ( "inst_index" ) .getTextValue ( ) .toInt ( ) }
1325
1426 Call getCall ( ) {
15- // TODO: handle calls spanning multiple lines
16- result .getLocation ( ) .hasLocationInfo ( this .call_filename ( ) , this .call_linenum ( ) , _, _, _)
27+ // TODO: do we handle calls spanning multiple lines?
28+ result .getLocation ( ) .hasLocationInfo ( this .get_filename_data ( ) , this .get_linenum_data ( ) , _, _, _)
1729 }
1830}
1931
20- class RecordedPythonCall extends RecordedCall {
21- RecordedPythonCall ( ) {
22- this .hasAttribute ( "pythoncallee_filename" ) and
23- this .hasAttribute ( "pythoncallee_linenum" ) and
24- this .hasAttribute ( "pythoncallee_funcname" )
25- }
32+ abstract class XMLCallee extends XMLElement { }
2633
27- string pythoncallee_filename ( ) { result = this .getAttributeValue ( "pythoncallee_filename" ) }
34+ class XMLPythonCallee extends XMLCallee {
35+ XMLPythonCallee ( ) { this .hasName ( "PythonCallee" ) }
2836
29- int pythoncallee_linenum ( ) { result = this .getAttributeValue ( "pythoncallee_linenum ") .toInt ( ) }
37+ string get_filename_data ( ) { result = this .getAChild ( "filename ") .getTextValue ( ) }
3038
31- string pythoncallee_funcname ( ) { result = this .getAttributeValue ( "pythoncallee_funcname" ) }
39+ int get_linenum_data ( ) { result = this .getAChild ( "linenum" ) .getTextValue ( ) .toInt ( ) }
40+
41+ string get_funcname_data ( ) { result = this .getAChild ( "funcname" ) .getTextValue ( ) }
3242
3343 Function getCallee ( ) {
34- result .getLocation ( ) .hasLocationInfo ( this .pythoncallee_filename ( ) , this .pythoncallee_linenum ( ) , _, _, _)
44+ result .getLocation ( ) .hasLocationInfo ( this .get_filename_data ( ) , this .get_linenum_data ( ) , _, _, _)
3545 }
3646}
3747
38- class RecordedBuiltinCall extends RecordedCall {
39- RecordedBuiltinCall ( ) {
40- this .hasAttribute ( "externalcallee_module" ) and
41- this .hasAttribute ( "externalcallee_qualname" ) and
42- this .getAttributeValue ( "externalcallee_is_builtin" ) = "True"
43- }
48+ class XMLExternalCallee extends XMLCallee {
49+ XMLExternalCallee ( ) { this .hasName ( "ExternalCallee" ) }
4450
45- string externalcallee_module ( ) { result = this .getAttributeValue ( "externalcallee_module" ) }
51+ string get_module_data ( ) { result = this .getAChild ( "module" ) . getTextValue ( ) }
4652
47- string externalcallee_qualname ( ) { result = this .getAttributeValue ( "externalcallee_qualname" ) }
53+ string get_qualname_data ( ) { result = this .getAChild ( "qualname" ) . getTextValue ( ) }
4854
4955 Builtin getCallee ( ) {
5056 exists ( Builtin mod |
51- not externalcallee_module ( ) = "None" and
57+ not this . get_module_data ( ) = "None" and
5258 mod .isModule ( ) and
53- mod .getName ( ) = this .externalcallee_module ( )
59+ mod .getName ( ) = this .get_module_data ( )
5460 or
55- externalcallee_module ( ) = "None" and
61+ this . get_module_data ( ) = "None" and
5662 mod = Builtin:: builtinModule ( )
5763 |
58- result = traverse_qualname ( mod , this .externalcallee_qualname ( ) )
64+ result = traverse_qualname ( mod , this .get_qualname_data ( ) )
5965 )
6066 }
6167}
6268
63- Builtin traverse_qualname ( Builtin parent , string qualname ) {
69+ private Builtin traverse_qualname ( Builtin parent , string qualname ) {
6470 not qualname = "__objclass__" and
6571 not qualname .matches ( "%.%" ) and
6672 result = parent .getMember ( qualname )
@@ -74,17 +80,48 @@ Builtin traverse_qualname(Builtin parent, string qualname) {
7480 )
7581}
7682
77-
7883/**
7984 * Class of recorded calls where we can uniquely identify both the `call` and the `callee`.
8085 */
81- class ValidRecordedCall extends RecordedCall {
86+ class ValidRecordedCall extends XMLRecordedCall {
8287 ValidRecordedCall ( ) {
8388 strictcount ( this .getCall ( ) ) = 1 and
8489 (
85- strictcount ( this .( RecordedPythonCall ) . getCall ( ) ) = 1
90+ strictcount ( this .getXMLCallee ( ) . ( XMLPythonCallee ) . getCallee ( ) ) = 1
8691 or
87- strictcount ( this .( RecordedBuiltinCall ) . getCall ( ) ) = 1
92+ strictcount ( this .getXMLCallee ( ) . ( XMLExternalCallee ) . getCallee ( ) ) = 1
8893 )
8994 }
9095}
96+
97+ class InvalidRecordedCall extends XMLRecordedCall {
98+ InvalidRecordedCall ( ) { not this instanceof ValidRecordedCall }
99+ }
100+
101+ module PointsToBasedCallGraph {
102+ class ResolvableRecordedCall extends ValidRecordedCall {
103+ Value calleeValue ;
104+
105+ ResolvableRecordedCall ( ) {
106+ exists ( Call call , XMLCallee xmlCallee |
107+ call = this .getCall ( ) and
108+ calleeValue .getACall ( ) = call .getAFlowNode ( ) and
109+ xmlCallee = this .getXMLCallee ( ) and
110+ (
111+ xmlCallee instanceof XMLPythonCallee and
112+ calleeValue .( PythonFunctionValue ) .getScope ( ) = xmlCallee .( XMLPythonCallee ) .getCallee ( )
113+ or
114+ xmlCallee instanceof XMLExternalCallee and
115+ calleeValue .( BuiltinFunctionObjectInternal ) .getBuiltin ( ) =
116+ xmlCallee .( XMLExternalCallee ) .getCallee ( )
117+ or
118+ xmlCallee instanceof XMLExternalCallee and
119+ calleeValue .( BuiltinMethodObjectInternal ) .getBuiltin ( ) =
120+ xmlCallee .( XMLExternalCallee ) .getCallee ( )
121+ )
122+ )
123+ }
124+
125+ Value getCalleeValue ( ) { result = calleeValue }
126+ }
127+ }
0 commit comments