Skip to content

Commit

Permalink
Fix anchor generation on titles with ampersands
Browse files Browse the repository at this point in the history
Fixes #696.
  • Loading branch information
robin850 committed Feb 27, 2021
1 parent cd1e3c7 commit 65511c5
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

* Fix anchor generation on titles with ampersands.

Fixes #696.

## Version 3.5.1 (Security)

* Fix a security vulnerability using `:quote` in combination with the
Expand Down
19 changes: 18 additions & 1 deletion ext/redcarpet/html.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,22 @@ rndr_linebreak(struct buf *ob, void *opaque)
return 1;
}

static int html_entity_ahead(const uint8_t *text, size_t start, size_t size) {
size_t i = start;

if (text[i] != '&')
return 0;

for (; i < size; ++i) {
if (text[i] == ' ')
return 0;
else if (text[i] == ';')
return 1;
}

return 0;
}

static void
rndr_header_anchor(struct buf *out, const struct buf *anchor)
{
Expand All @@ -293,10 +309,11 @@ rndr_header_anchor(struct buf *out, const struct buf *anchor)
while (i < size && a[i] != '>')
i++;
// skip html entities
} else if (a[i] == '&') {
} else if (a[i] == '&' && html_entity_ahead(a, i, size)) {
while (i < size && a[i] != ';')
i++;
}

// replace non-ascii or invalid characters with dashes
else if (!isascii(a[i]) || strchr(STRIPPED, a[i])) {
if (inserted && !stripped)
Expand Down
7 changes: 5 additions & 2 deletions test/html_toc_render_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,17 @@ def test_toc_heading_with_hyphen_and_equal
end

def test_anchor_generation_with_edge_cases
# Imported from ActiveSupport::Inflector#parameterize's tests
# Mostly imported from ActiveSupport::Inflector#parameterize's tests
titles = {
"Donald E. Knuth" => "donald-e-knuth",
"Random text with *(bad)* characters" => "random-text-with-bad-characters",
"!@#Surrounding bad characters!@#" => "surrounding-bad-characters",
"Squeeze separators" => "squeeze-separators",
"Test with + sign" => "test-with-sign",
"Test with a Namespaced::Class" => "test-with-a-namespaced-class"
"Test with a Namespaced::Class" => "test-with-a-namespaced-class",
"Foo & Bar" => "foo-bar",
"Foo&Bar" => "foo-bar",
"Foo &amp; Bar" => "foo-bar"
}

titles.each do |title, anchor|
Expand Down

0 comments on commit 65511c5

Please sign in to comment.