Skip to content

Commit 83fe8d8

Browse files
committed
Fixes #2159 -- Do not HTML-escape traces in the cache and profiling panel
The panel data has to be explicitly reloaded from the store to hit this case. The new ``reload_stats`` utility helps with this.
1 parent b40dd8a commit 83fe8d8

File tree

6 files changed

+25
-2
lines changed

6 files changed

+25
-2
lines changed

debug_toolbar/templates/debug_toolbar/panels/cache.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ <h4>{% translate "Calls" %}</h4>
6161
</tr>
6262
<tr class="djUnselected djToggleDetails_{{ forloop.counter }}" id="cacheDetails_{{ forloop.counter }}">
6363
<td colspan="1"></td>
64-
<td colspan="5"><pre class="djdt-stack">{{ call.trace }}</pre></td>
64+
<td colspan="5"><pre class="djdt-stack">{{ call.trace|safe }}</pre></td>
6565
</tr>
6666
{% endfor %}
6767
</tbody>

debug_toolbar/templates/debug_toolbar/panels/profiling.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
{% else %}
2121
<span class="djNoToggleSwitch"></span>
2222
{% endif %}
23-
<span class="djdt-stack">{{ call.func_std_string }}</span>
23+
<span class="djdt-stack">{{ call.func_std_string|safe }}</span>
2424
</div>
2525
</td>
2626
<td>{{ call.cumtime|floatformat:3 }}</td>

tests/base.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ def assertValidHTML(self, content):
112112
msg_parts.append(f" {lines[position[0] - 1]}")
113113
raise self.failureException("\n".join(msg_parts))
114114

115+
def reload_stats(self):
116+
data = self.toolbar.store.panel(self.toolbar.request_id, self.panel_id)
117+
self.panel.load_stats_from_store(data)
118+
115119

116120
class BaseTestCase(BaseMixin, TestCase):
117121
pass

tests/panels/test_cache.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,13 @@ def test_insert_content(self):
124124
# ensure the panel does not have content yet.
125125
self.assertNotIn("café", self.panel.content)
126126
self.panel.generate_stats(self.request, response)
127+
self.reload_stats()
127128
# ensure the panel renders correctly.
128129
content = self.panel.content
129130
self.assertIn("café", content)
130131
self.assertValidHTML(content)
132+
# ensure traces aren't escaped
133+
self.assertIn('<span class="djdt-path">', content)
131134

132135
def test_generate_server_timing(self):
133136
self.assertEqual(len(self.panel.calls), 0)

tests/panels/test_profiling.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@ def test_insert_content(self):
3535
# ensure the panel does not have content yet.
3636
self.assertNotIn("regular_view", self.panel.content)
3737
self.panel.generate_stats(self.request, response)
38+
self.reload_stats()
3839
# ensure the panel renders correctly.
3940
content = self.panel.content
4041
self.assertIn("regular_view", content)
4142
self.assertIn("render", content)
4243
self.assertValidHTML(content)
44+
# ensure traces aren't escaped
45+
self.assertIn('<span class="djdt-path">', content)
4346

4447
@override_settings(DEBUG_TOOLBAR_CONFIG={"PROFILER_THRESHOLD_RATIO": 1})
4548
def test_cum_time_threshold(self):

tests/test_store.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from django.test import TestCase
44
from django.test.utils import override_settings
5+
from django.utils.safestring import SafeData, mark_safe
56

67
from debug_toolbar import store
78

@@ -97,6 +98,18 @@ def test_panel(self):
9798
self.store.save_panel("bar", "bar.panel", {"a": 1})
9899
self.assertEqual(self.store.panel("bar", "bar.panel"), {"a": 1})
99100

101+
def test_serialize_safestring(self):
102+
before = {"string": mark_safe("safe")}
103+
104+
self.store.save_panel("bar", "bar.panel", before)
105+
after = self.store.panel("bar", "bar.panel")
106+
107+
self.assertFalse(type(before["string"]) is str)
108+
self.assertTrue(isinstance(before["string"], SafeData))
109+
110+
self.assertTrue(type(after["string"]) is str)
111+
self.assertFalse(isinstance(after["string"], SafeData))
112+
100113

101114
class StubStore(store.BaseStore):
102115
pass

0 commit comments

Comments
 (0)