-
-
Notifications
You must be signed in to change notification settings - Fork 32.8k
Fixed #35673 -- Enhanced ExceptionReporter
to handle GET and FILES parameters
#19702
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, this is a great start ⭐
tests/view_tests/tests/test_debug.py
Outdated
@@ -486,6 +486,14 @@ def test_template_override_exception_reporter(self): | |||
response = self.client.get("/raises500/", headers={"accept": "text/plain"}) | |||
self.assertContains(response, "Oh dear, an error occurred!", status_code=500) | |||
|
|||
@override_settings(DATA_UPLOAD_MAX_NUMBER_FIELDS=1) | |||
def test_max_number_of_fields_exceeded(self): | |||
response = self.client.get("/raises500/", {"a": "1", "b": "2"}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
response = self.client.get("/raises500/", {"a": "1", "b": "2"}) | |
with self.assertLogs("django.request", "ERROR"): | |
response = self.client.get("/raises500/", {"a": "1", "b": "2"}) |
We want to capture the logging so we don't get noise when running the test
django/views/debug.py
Outdated
@@ -389,7 +411,7 @@ def get_traceback_data(self): | |||
"is_email": self.is_email, | |||
"unicode_hint": unicode_hint, | |||
"frames": frames, | |||
"request": self.request, | |||
"request": SafeExceptionRequest(self.request) if self.request else None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"request": SafeExceptionRequest(self.request) if self.request else None, | |
"request": self.request, |
We can revert this and remove the SafeExceptionRequest
and instead do:
--- a/django/views/templates/technical_500.html
+++ b/django/views/templates/technical_500.html
@@ -354,7 +354,7 @@ Exception Value: {{ exception_value|force_escape }}{% if exception_notes %}{{ ex
{% endif %}
<h3 id="get-info">GET</h3>
- {% if request.GET %}
+ {% if request_GET_items %}
<table class="req">
<thead>
<tr>
@@ -398,7 +398,7 @@ Exception Value: {{ exception_value|force_escape }}{% if exception_notes %}{{ ex
{% endif %}
<h3 id="files-info">FILES</h3>
- {% if request.FILES %}
+ {% if request_FILES_items %}
<table class="req">
<thead>
<tr>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also think in the template we should consider rendering the error differently rather than have it within a table with "Variable", "Value" headers, something like:
<h3 id="files-info">FILES</h3>
- {% if request.FILES %}
+ {% if request_FILES_items %}
<table class="req">
<thead>
<tr>
@@ -415,6 +415,8 @@ Exception Value: {{ exception_value|force_escape }}{% if exception_notes %}{{ ex
<h3 id="files-info">FILES</h3>
- {% if request.FILES %}
+ {% if request_FILES_items %}
<table class="req">
<thead>
<tr>
@@ -415,6 +415,8 @@ Exception Value: {{ exception_value|force_escape }}{% if exception_notes %}{{ ex
{% endfor %}
</tbody>
</table>
+ {% elif request_FILES_error %}
+ <p>{{ request_FILES_error }}</p>
{% else %}
<p>No FILES data</p>
{% endif %}
Where request_FILES_error
is the error if available and ""
or None
otherwise
django/views/debug.py
Outdated
try: | ||
c["request_FILES_items"] = self.request.FILES.items() | ||
except TooManyFilesSent: | ||
c["request_FILES_items"] = [ | ||
( | ||
"<could not parse>", | ||
"Number of FILES parameters exceeded " | ||
"DATA_UPLOAD_MAX_NUMBER_FILES", | ||
) | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try: | |
c["request_FILES_items"] = self.request.FILES.items() | |
except TooManyFilesSent: | |
c["request_FILES_items"] = [ | |
( | |
"<could not parse>", | |
"Number of FILES parameters exceeded " | |
"DATA_UPLOAD_MAX_NUMBER_FILES", | |
) | |
] | |
c["request_FILES_items"] = self.request.FILES.items() |
Note that this can be reverted without any test failures
We might also want to test for (and possibly handle) too many POST parameters
django/views/debug.py
Outdated
"Number of GET paramters exceeded " | ||
"DATA_UPLOAD_MAX_NUMBER_FIELDS.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think instead of us defining new text, we can use the text from the error itself (note there is a typo here)
tests/view_tests/views.py
Outdated
@@ -45,7 +46,7 @@ def raises500(request): | |||
# We need to inspect the HTML generated by the fancy 500 debug view but | |||
# the test client ignores it, so we send it explicitly. | |||
try: | |||
raise Exception | |||
raise Exception("Test exception to trigger debug view") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
raise Exception("Test exception to trigger debug view") | |
raise Exception |
This change is not needed
Trac ticket number
ticket-35673
Branch description
Problem:
Django's ExceptionReporter crashes with infinite loops when handling requests that exceed
DATA_UPLOAD_MAX_NUMBER_FIELDS
limits, resulting in blank 500 error pages instead of useful debug information.Solution:
Implemented
SafeExceptionRequest
wrapper class that safely handlesrequest.GET
andrequest.FILES
access by catchingTooManyFieldsSent
/TooManyFilesSent
exceptions and returning empty collections with error indicators.Checklist
main
branch.