@@ -852,6 +852,26 @@ module PrivateDjango {
852
852
)
853
853
}
854
854
855
+ /**
856
+ * Gets the synthetic node where data could be loaded from, when a fetch is
857
+ * made on `modelClass`.
858
+ *
859
+ * In vanilla Django inheritance, this is simply the model itself, but if a
860
+ * model is based on `polymorphic.models.PolymorphicModel`, a fetch of the
861
+ * base-class can also yield instances of its subclasses.
862
+ */
863
+ SyntheticDjangoOrmModelNode nodeToLoadFrom ( API:: Node modelClass ) {
864
+ result .getModelClass ( ) = modelClass
865
+ or
866
+ exists ( API:: Node polymorphicModel |
867
+ polymorphicModel =
868
+ API:: moduleImport ( "polymorphic" ) .getMember ( "models" ) .getMember ( "PolymorphicModel" )
869
+ |
870
+ polymorphicModel .getASubclass + ( ) = modelClass and
871
+ modelClass .getASubclass + ( ) = result .getModelClass ( )
872
+ )
873
+ }
874
+
855
875
/** Additional data-flow steps for Django ORM models. */
856
876
class DjangOrmSteps extends AdditionalOrmSteps {
857
877
override predicate storeStep (
@@ -908,15 +928,15 @@ module PrivateDjango {
908
928
or
909
929
// synthetic -> method-call that returns collection of ORM models (all/filter/...)
910
930
exists ( API:: Node modelClass |
911
- nodeFrom . ( SyntheticDjangoOrmModelNode ) . getModelClass ( ) = modelClass and
931
+ nodeFrom = nodeToLoadFrom ( modelClass ) and
912
932
nodeTo .( Model:: QuerySetMethodInstanceCollection ) .getModelClass ( ) = modelClass and
913
933
nodeTo .( Model:: QuerySetMethodInstanceCollection ) .isDbFetch ( ) and
914
934
c instanceof DataFlow:: ListElementContent
915
935
)
916
936
or
917
937
// synthetic -> method-call that returns dictionary with ORM models as values
918
938
exists ( API:: Node modelClass |
919
- nodeFrom . ( SyntheticDjangoOrmModelNode ) . getModelClass ( ) = modelClass and
939
+ nodeFrom = nodeToLoadFrom ( modelClass ) and
920
940
nodeTo .( Model:: QuerySetMethodInstanceDictValue ) .getModelClass ( ) = modelClass and
921
941
nodeTo .( Model:: QuerySetMethodInstanceDictValue ) .isDbFetch ( ) and
922
942
c instanceof DataFlow:: DictionaryElementAnyContent
@@ -938,9 +958,9 @@ module PrivateDjango {
938
958
or
939
959
// synthetic -> method-call that returns single ORM model (get/first/...)
940
960
exists ( API:: Node modelClass |
961
+ nodeFrom = nodeToLoadFrom ( modelClass ) and
941
962
nodeTo .( Model:: InstanceSource ) .getModelClass ( ) = modelClass and
942
- nodeTo .( Model:: InstanceSource ) .isDbFetch ( ) and
943
- nodeFrom .( SyntheticDjangoOrmModelNode ) .getModelClass ( ) = modelClass
963
+ nodeTo .( Model:: InstanceSource ) .isDbFetch ( )
944
964
)
945
965
}
946
966
}
0 commit comments