This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git
The following commit(s) were added to refs/heads/master by this push:
new 1fc06751a enforce text limits for all markdown rendering paths
1fc06751a is described below
commit 1fc06751a151a3482c5cdbb607077f2db12911d9
Author: Dave Brondsema <[email protected]>
AuthorDate: Thu Jun 11 11:39:08 2026 -0400
enforce text limits for all markdown rendering paths
---
Allura/allura/lib/app_globals.py | 31 ++++++++++++++++++++++++-------
Allura/allura/lib/search.py | 4 ++++
Allura/allura/tests/test_globals.py | 18 ++++++++++++++++++
Allura/development.ini | 2 ++
4 files changed, 48 insertions(+), 7 deletions(-)
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index 90f1714e3..a7811f3f2 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -100,8 +100,14 @@ def toc_slugify_with_prefix(value, separator):
'mdx_breakless_lists',],
output_format='html')
- def convert(self, source, render_limit=True) -> Markup:
- if render_limit and len(source) >
asint(config.get('markdown_render_max_length', 80000)):
+ @staticmethod
+ def base_render_limit() -> int:
+ return asint(config.get('markdown_render_max_length', 80000))
+
+ def convert(self, source, max_length=None) -> Markup:
+ if max_length is None:
+ max_length = self.base_render_limit()
+ if len(source) > max_length:
# if text is too big, markdown can take a long time to process it,
# so we return it as a plain text
log.info('Text is too big. Skipping markdown processing')
@@ -145,7 +151,8 @@ def cached_convert(self, artifact: MappedClass, field_name:
str) -> Markup:
# Convert the markdown and time the result.
start = time.time()
- html = self.convert(source_text, render_limit=False)
+ cached_max_length =
asint(config.get('markdown_render_max_length.cached', self.base_render_limit()
* 2))
+ html = self.convert(source_text, max_length=cached_max_length)
render_time = time.time() - start
threshold = config.get('markdown_cache_threshold')
@@ -189,6 +196,19 @@ def cached_convert(self, artifact: MappedClass,
field_name: str) -> Markup:
return html
+class ForgeMarkdownCommit(ForgeMarkdown):
+
+ def __init__(self, app):
+ super().__init__()
+ self.app = app
+
+ def make_markdown_instance(self, **forge_ext_kwargs):
+ return markdown.Markdown(
+ extensions=[CommitMessageExtension(self.app), EmojiExtension(),
'markdown.extensions.nl2br'],
+ output_format='html',
+ )
+
+
class Globals:
"""Container for objects available throughout the life of the application.
@@ -520,10 +540,7 @@ def markdown_commit(self):
"""
app = getattr(c, 'app', None)
- return markdown.Markdown(
- extensions=[CommitMessageExtension(app), EmojiExtension(),
'markdown.extensions.nl2br'],
- output_format='html',
- )
+ return ForgeMarkdownCommit(app)
@property
def production_mode(self):
diff --git a/Allura/allura/lib/search.py b/Allura/allura/lib/search.py
index 4e832261b..b234a863b 100644
--- a/Allura/allura/lib/search.py
+++ b/Allura/allura/lib/search.py
@@ -415,7 +415,11 @@ def filter_unauthorized(doc):
def find_shortlinks(text):
from .markdown_extensions import ForgeExtension
+ from .app_globals import ForgeMarkdown
+ if len(text) > ForgeMarkdown.base_render_limit():
+ log.info('Text is too big. Skipping shortlink search')
+ return []
md = markdown.Markdown(
extensions=['markdown.extensions.codehilite', ForgeExtension(),
'markdown.extensions.tables'],
output_format='html')
diff --git a/Allura/allura/tests/test_globals.py
b/Allura/allura/tests/test_globals.py
index 0c7331d02..ab1a09c17 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -42,6 +42,7 @@
from allura import model as M
from allura.lib import helpers as h
from allura.lib.app_globals import ForgeMarkdown
+from allura.lib.search import find_shortlinks
from allura.tests import decorators as td
from forgewiki import model as WM
@@ -445,6 +446,11 @@ def test_markdown_big_text(self):
assert g.markdown.convert(text) == '<pre>%s</pre>' % text
assert g.markdown_wiki.convert(text) == '<pre>%s</pre>' % text
assert g.markdown.convert('<b>' + text) == '<pre><b>%s</pre>' %
text
+ assert g.markdown_commit.convert(text) == '<pre>%s</pre>' % text
+
+ def test_find_shortlinks_big_text(self):
+ text = '[a123] ' + 'a' * 40001
+ assert find_shortlinks(text) == []
def test_markdown_basics(self):
with h.push_context('test', 'wiki', neighborhood='Projects'):
@@ -922,6 +928,18 @@ def test_render_time_below_threshold(self):
assert self.post.text_cache.html is None
assert self.post.text_cache.render_time is None
+ @patch.dict('allura.lib.app_globals.config',
markdown_cache_threshold='99999')
+ def test_big_text(self):
+ # between the base limit and the higher .cached limit (2x by default),
still renders
+ self.post.text = 'a' * 50000
+ html = self.md.cached_convert(self.post, 'text')
+ assert not html.startswith('<pre>')
+ # beyond the .cached limit, falls back to plain text
+ self.post.text = 'a' * 80001
+ del self.post.text_cache
+ html = self.md.cached_convert(self.post, 'text')
+ assert html == '<pre>%s</pre>' % self.post.text
+
@patch.dict('allura.lib.app_globals.config', {})
def test_all_expected_keys_exist_in_cache(self):
self.md.cached_convert(self.post, 'text')
diff --git a/Allura/development.ini b/Allura/development.ini
index 3193b5331..62d03b9f1 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -664,6 +664,8 @@ site_notification.impressions = 0
markdown_cache_threshold = .1
; markdown text longer than max length will not be converted to html
markdown_render_max_length = 200000
+; higher limit for renders that can be cached (defaults to 2x
markdown_render_max_length)
+;markdown_render_max_length.cached =
; Don't add rel=nofollow to these domains when generating links from Markdown
content
;nofollow_exempt_domains =