Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
- [pull #734] Fix empty list items being parsed as nested lists (#167)
- [pull #735] Fix `smarty-pants` extra converting quotes inside inline HTML tags and comments (#150)
- [pull #737] Fix XSS from code spans that the span gamut doesn't treat as code spans in safe mode (#726)
- [pull #738] Fix `<` in code blocks being escaped twice in safe mode (#240)


## python-markdown2 2.5.5
Expand Down
9 changes: 6 additions & 3 deletions lib/markdown2.py
Original file line number Diff line number Diff line change
Expand Up @@ -1677,7 +1677,7 @@ def header_id_from_text(self,
None to not have an id attribute and to exclude this header from
the TOC (if the "toc" extra is specified).
"""
header_id = _slugify(html.unescape(text))
header_id = _slugify(html.unescape(self._unescape_special_chars(text)))
if prefix and isinstance(prefix, str):
header_id = prefix + '-' + header_id

Expand Down Expand Up @@ -2335,10 +2335,13 @@ def _encode_incomplete_tags(self, text: str) -> str:

def incomplete_tags_sub(match):
text = match.group()
# hash the `&lt;` so that code blocks don't escape it a second time
lt_hash = self._hash_span('&lt;')
self._code_table['&lt;'] = lt_hash
# ensure that we handle escaped incomplete tags properly by consuming and replacing the escapes
if not self._is_unescaped_re.match(text):
text = text.replace('\\<', '&lt;')
return text.replace('<', '&lt;')
text = text.replace('\\<', lt_hash)
return text.replace('<', lt_hash)

text = self._incomplete_tags_re.sub(incomplete_tags_sub, text)

Expand Down
27 changes: 27 additions & 0 deletions test/tm-cases/safe_mode_incomplete_tags_in_code_blocks.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<h1 id="comparing-ab">Comparing a&lt;b</h1>

<p>Start of test.</p>

<pre><code>for (i=0; i&lt;3; i++) {
printf("Hello, world.");
}
</code></pre>

<blockquote>
<p>This is a quote</p>
</blockquote>

<pre><code>if (a&lt;b &amp;&amp; b&lt;c) {}
</code></pre>

<ul>
<li><p>list item</p>

<pre><code>x&lt;y
</code></pre></li>
</ul>

<p>These are still escaped: a&lt;b and &lt;c</p>

<pre><code>Literal entity: &amp;lt;div
</code></pre>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{'safe_mode': 'escape', 'extras': ['fenced-code-blocks', 'header-ids']}
21 changes: 21 additions & 0 deletions test/tm-cases/safe_mode_incomplete_tags_in_code_blocks.text
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Comparing a<b

Start of test.

for (i=0; i<3; i++) {
printf("Hello, world.");
}

> This is a quote

```
if (a<b && b<c) {}
```

- list item

x<y

These are still escaped: a<b and <c

Literal entity: &lt;div
Loading