@@ -35,7 +35,7 @@ private module Django {
3535 * WARNING: Only holds for a few predefined attributes.
3636 */
3737 private DataFlow:: Node django_attr ( DataFlow:: TypeTracker t , string attr_name ) {
38- attr_name in [ "db" , "urls" , "http" , "conf" ] and
38+ attr_name in [ "db" , "urls" , "http" , "conf" , "shortcuts" ] and
3939 (
4040 t .start ( ) and
4141 result = DataFlow:: importNode ( "django" + "." + attr_name )
@@ -1649,6 +1649,62 @@ private module Django {
16491649 }
16501650 }
16511651 }
1652+
1653+ // -------------------------------------------------------------------------
1654+ // django.shortcuts
1655+ // -------------------------------------------------------------------------
1656+ /** Gets a reference to the `django.shortcuts` module. */
1657+ DataFlow:: Node shortcuts ( ) { result = django_attr ( "shortcuts" ) }
1658+
1659+ /** Provides models for the `django.shortcuts` module */
1660+ module shortcuts {
1661+ /**
1662+ * Gets a reference to the attribute `attr_name` of the `django.shortcuts` module.
1663+ * WARNING: Only holds for a few predefined attributes.
1664+ */
1665+ private DataFlow:: Node shortcuts_attr ( DataFlow:: TypeTracker t , string attr_name ) {
1666+ attr_name in [ "redirect" ] and
1667+ (
1668+ t .start ( ) and
1669+ result = DataFlow:: importNode ( "django.shortcuts" + "." + attr_name )
1670+ or
1671+ t .startInAttr ( attr_name ) and
1672+ result = shortcuts ( )
1673+ )
1674+ or
1675+ // Due to bad performance when using normal setup with `shortcuts_attr(t2, attr_name).track(t2, t)`
1676+ // we have inlined that code and forced a join
1677+ exists ( DataFlow:: TypeTracker t2 |
1678+ exists ( DataFlow:: StepSummary summary |
1679+ shortcuts_attr_first_join ( t2 , attr_name , result , summary ) and
1680+ t = t2 .append ( summary )
1681+ )
1682+ )
1683+ }
1684+
1685+ pragma [ nomagic]
1686+ private predicate shortcuts_attr_first_join (
1687+ DataFlow:: TypeTracker t2 , string attr_name , DataFlow:: Node res ,
1688+ DataFlow:: StepSummary summary
1689+ ) {
1690+ DataFlow:: StepSummary:: step ( shortcuts_attr ( t2 , attr_name ) , res , summary )
1691+ }
1692+
1693+ /**
1694+ * Gets a reference to the attribute `attr_name` of the `django.shortcuts` module.
1695+ * WARNING: Only holds for a few predefined attributes.
1696+ */
1697+ private DataFlow:: Node shortcuts_attr ( string attr_name ) {
1698+ result = shortcuts_attr ( DataFlow:: TypeTracker:: end ( ) , attr_name )
1699+ }
1700+
1701+ /**
1702+ * Gets a reference to the `django.shortcuts.redirect` function
1703+ *
1704+ * See https://docs.djangoproject.com/en/3.1/topics/http/shortcuts/#redirect
1705+ */
1706+ DataFlow:: Node redirect ( ) { result = shortcuts_attr ( "redirect" ) }
1707+ }
16521708 }
16531709
16541710 // ---------------------------------------------------------------------------
@@ -1956,4 +2012,32 @@ private module Django {
19562012 )
19572013 }
19582014 }
2015+
2016+ // ---------------------------------------------------------------------------
2017+ // django.shortcuts.redirect
2018+ // ---------------------------------------------------------------------------
2019+ /**
2020+ * A call to `django.shortcuts.redirect`.
2021+ *
2022+ * Note: This works differently depending on what argument is used.
2023+ * _One_ option is to redirect to a full URL.
2024+ *
2025+ * See https://docs.djangoproject.com/en/3.1/topics/http/shortcuts/#redirect
2026+ */
2027+ private class DjangoShortcutsRedirectCall extends HTTP:: Server:: HttpRedirectResponse:: Range ,
2028+ DataFlow:: CfgNode {
2029+ override CallNode node ;
2030+
2031+ DjangoShortcutsRedirectCall ( ) { node .getFunction ( ) = django:: shortcuts:: redirect ( ) .asCfgNode ( ) }
2032+
2033+ override DataFlow:: Node getRedirectLocation ( ) {
2034+ result .asCfgNode ( ) in [ node .getArg ( 0 ) , node .getArgByName ( "to" ) ]
2035+ }
2036+
2037+ override DataFlow:: Node getBody ( ) { none ( ) }
2038+
2039+ override DataFlow:: Node getMimetypeOrContentTypeArg ( ) { none ( ) }
2040+
2041+ override string getMimetypeDefault ( ) { none ( ) }
2042+ }
19592043}
0 commit comments