Skip to content

Commit a492485

Browse files
committed
Python: Model known form/field subclasses in Django
I used some ad-hoc QL queries to help me find all these extra instances, but not quite ready to share that code yet :P
1 parent 8d0f608 commit a492485

File tree

1 file changed

+163
-8
lines changed

1 file changed

+163
-8
lines changed

python/ql/src/semmle/python/frameworks/Django.qll

Lines changed: 163 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1979,40 +1979,195 @@ private module Django {
19791979
/** Provides models for django forms (defined in the `django.forms` module) */
19801980
module Forms {
19811981
/**
1982-
* Provides models for the `django.forms.Form` class and subclasses.
1982+
* Provides models for the `django.forms.forms.BaseForm` class and subclasses. This
1983+
* is usually used by the `django.forms.forms.Form` class, which is also available
1984+
* under the more commonly used alias `django.forms.Form`.
19831985
*
19841986
* See https://docs.djangoproject.com/en/3.1/ref/forms/api/
19851987
*/
19861988
module Form {
1987-
/** Gets a reference to the `django.forms.Form` class or any subclass. */
1989+
/** Gets a reference to the `django.forms.forms.BaseForm` class or any subclass. */
19881990
API::Node subclassRef() {
1991+
// canonical definition
19891992
result =
19901993
API::moduleImport("django")
1994+
.getMember("forms")
1995+
.getMember("forms")
1996+
.getMember(["BaseForm", "Form"])
1997+
.getASubclass*()
1998+
or
1999+
result =
2000+
API::moduleImport("django")
2001+
.getMember("forms")
2002+
.getMember("models")
2003+
.getMember(["BaseModelForm", "ModelForm"])
2004+
.getASubclass*()
2005+
or
2006+
// aliases from `django.forms`
2007+
result =
2008+
API::moduleImport("django")
2009+
.getMember("forms")
2010+
.getMember(["BaseForm", "Form", "BaseModelForm", "ModelForm"])
2011+
.getASubclass*()
2012+
or
2013+
// other Form subclasses defined in Django
2014+
result =
2015+
API::moduleImport("django")
2016+
.getMember("contrib")
2017+
.getMember("admin")
2018+
.getMember("forms")
2019+
.getMember(["AdminAuthenticationForm", "AdminPasswordChangeForm"])
2020+
.getASubclass*()
2021+
or
2022+
result =
2023+
API::moduleImport("django")
2024+
.getMember("contrib")
2025+
.getMember("admin")
2026+
.getMember("helpers")
2027+
.getMember("ActionForm")
2028+
.getASubclass*()
2029+
or
2030+
result =
2031+
API::moduleImport("django")
2032+
.getMember("contrib")
2033+
.getMember("admin")
2034+
.getMember("views")
2035+
.getMember("main")
2036+
.getMember("ChangeListSearchForm")
2037+
.getASubclass*()
2038+
or
2039+
result =
2040+
API::moduleImport("django")
2041+
.getMember("contrib")
2042+
.getMember("auth")
19912043
.getMember("forms")
19922044
.getMember([
1993-
"Form"
1994-
// TODO: Known subclasses
2045+
"PasswordResetForm", "UserChangeForm", "SetPasswordForm",
2046+
"AdminPasswordChangeForm", "PasswordChangeForm", "AuthenticationForm",
2047+
"UserCreationForm"
19952048
])
19962049
.getASubclass*()
2050+
or
2051+
result =
2052+
API::moduleImport("django")
2053+
.getMember("contrib")
2054+
.getMember("flatpages")
2055+
.getMember("forms")
2056+
.getMember("FlatpageForm")
2057+
.getASubclass*()
2058+
or
2059+
result =
2060+
API::moduleImport("django")
2061+
.getMember("forms")
2062+
.getMember("formsets")
2063+
.getMember("ManagementForm")
2064+
.getASubclass*()
2065+
or
2066+
result =
2067+
API::moduleImport("django")
2068+
.getMember("forms")
2069+
.getMember("models")
2070+
.getMember(["ModelForm", "BaseModelForm"])
2071+
.getASubclass*()
19972072
}
19982073
}
19992074

20002075
/**
2001-
* Provides models for the `django.forms.Field` class and subclasses.
2076+
* Provides models for the `django.forms.fields.Field` class and subclasses. This is
2077+
* also available under the more commonly used alias `django.forms.Field`.
20022078
*
20032079
* See https://docs.djangoproject.com/en/3.1/ref/forms/fields/
20042080
*/
20052081
module Field {
2006-
/** Gets a reference to the `django.forms.Form` class or any subclass. */
2082+
/** Gets a reference to the `django.forms.fields.Field` class or any subclass. */
20072083
API::Node subclassRef() {
2084+
exists(string modName, string clsName |
2085+
// canonical definition
2086+
result =
2087+
API::moduleImport("django")
2088+
.getMember("forms")
2089+
.getMember(modName)
2090+
.getMember(clsName)
2091+
.getASubclass*()
2092+
or
2093+
// alias from `django.forms`
2094+
result = API::moduleImport("django").getMember("forms").getMember(clsName).getASubclass*()
2095+
|
2096+
modName = "fields" and
2097+
clsName in [
2098+
"Field",
2099+
// Known subclasses
2100+
"BooleanField", "IntegerField", "CharField", "SlugField", "DateTimeField",
2101+
"EmailField", "DateField", "TimeField", "DurationField", "DecimalField", "FloatField",
2102+
"GenericIPAddressField", "UUIDField", "JSONField", "FilePathField",
2103+
"NullBooleanField", "URLField", "TypedChoiceField", "FileField", "ImageField",
2104+
"RegexField", "ChoiceField", "MultipleChoiceField", "ComboField", "MultiValueField",
2105+
"SplitDateTimeField", "TypedMultipleChoiceField", "BaseTemporalField"
2106+
]
2107+
or
2108+
// Known subclasses from `django.forms.models`
2109+
modName = "models" and
2110+
clsName in ["ModelChoiceField", "ModelMultipleChoiceField", "InlineForeignKeyField"]
2111+
)
2112+
or
2113+
// other Field subclasses defined in Django
20082114
result =
20092115
API::moduleImport("django")
2116+
.getMember("contrib")
2117+
.getMember("auth")
20102118
.getMember("forms")
2119+
.getMember(["ReadOnlyPasswordHashField", "UsernameField"])
2120+
.getASubclass*()
2121+
or
2122+
result =
2123+
API::moduleImport("django")
2124+
.getMember("contrib")
2125+
.getMember("gis")
2126+
.getMember("forms")
2127+
.getMember("fields")
20112128
.getMember([
2012-
"Field"
2013-
// TODO: Known subclasses
2129+
"GeometryCollectionField", "GeometryField", "LineStringField",
2130+
"MultiLineStringField", "MultiPointField", "MultiPolygonField", "PointField",
2131+
"PolygonField"
20142132
])
20152133
.getASubclass*()
2134+
or
2135+
result =
2136+
API::moduleImport("django")
2137+
.getMember("contrib")
2138+
.getMember("postgres")
2139+
.getMember("forms")
2140+
.getMember("array")
2141+
.getMember(["SimpleArrayField", "SplitArrayField"])
2142+
.getASubclass*()
2143+
or
2144+
result =
2145+
API::moduleImport("django")
2146+
.getMember("contrib")
2147+
.getMember("postgres")
2148+
.getMember("forms")
2149+
.getMember("hstore")
2150+
.getMember("HStoreField")
2151+
.getASubclass*()
2152+
or
2153+
result =
2154+
API::moduleImport("django")
2155+
.getMember("contrib")
2156+
.getMember("postgres")
2157+
.getMember("forms")
2158+
.getMember("ranges")
2159+
.getMember([
2160+
"BaseRangeField", "DateRangeField", "DateTimeRangeField", "DecimalRangeField",
2161+
"IntegerRangeField"
2162+
])
2163+
.getASubclass*()
2164+
or
2165+
result =
2166+
API::moduleImport("django")
2167+
.getMember("forms")
2168+
.getMember("models")
2169+
.getMember(["InlineForeignKeyField", "ModelChoiceField", "ModelMultipleChoiceField"])
2170+
.getASubclass*()
20162171
}
20172172
}
20182173
}

0 commit comments

Comments
 (0)