XRENDERING-815: XWiki syntax renderer doesn't escape closing macro syntax in various attributes - #433
Merged
Merged
Conversation
…ntax in various attributes
* Escape the "{" runs of every value that the renderer serializes as-is:
* (%...%) parameter values
* link and image references, their parameters, and the xwiki/2.1
queryString and anchor reference parameters
* the id macro name, which had no escaping at all and could also be
broken by a quote in the name
* Introduce XWikiSyntaxEscapeHandler#escapeCurlyBrackets as escaping
helper that correctly escapes every character of a run of "{" instead
of only the pairs: the previous two-pass "{{{"-then-"{{" replacement
corrupted runs of four "{" and left a literal "{{" behind for runs of
five, so it could still break out of a macro.
* For free-standing references which cannot be escaped at all, fall back
to the full [[...]] syntax when printing the reference free-standing
would put a "{{" into the output, as that could close the macro the
reference is serialized in. This is only about the macro syntax: the
image and attachment tokens of the parser accept a "{{" and parse such
a reference back unchanged, and where they don't - the URI token
accepts no "{" at all - the reference is truncated just like by every
other character that token rejects (a "}" or a "," for instance). That
pre-existing limitation of free-standing references is not addressed
here.
* Correctly escape the reference of links that were initially
freestanding when forced into the full syntax.
* Expect [[~{~{macro}}]] in links6.test: the escaped form parses back to
the very same reference while the previous output could badly
interfere with outer macro syntax.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Needs a closer look
XWikiSyntaxChainingRenderer can still emit an IdBlock incorrectly after a preceding {; it should use the inline-macro printing path.
Pull request overview
Fixes XWiki 2.0/2.1 renderer round-trip issues caused by unescaped {{ sequences in macro content.
Changes:
- Adds robust curly-bracket escaping for parameters, references, IDs, and link metadata.
- Uses full link syntax for unsafe free-standing references.
- Adds regression and round-trip tests.
File summaries
| File | Description |
|---|---|
xwiki-rendering-syntaxes/xwiki-rendering-syntax-xwiki21/src/test/java/org/xwiki/rendering/internal/renderer/xwiki21/XWikiSyntaxMacroContentRoundTripTest.java |
Adds XWiki 2.1 macro-content round-trip coverage. |
xwiki-rendering-syntaxes/xwiki-rendering-syntax-xwiki21/src/main/java/org/xwiki/rendering/internal/renderer/xwiki21/reference/XWikiSyntaxResourceRenderer.java |
Escapes XWiki 2.1 references, query strings, anchors, and link parameters. |
xwiki-rendering-syntaxes/xwiki-rendering-syntax-xwiki20/src/test/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxMacroContentRoundTripTest.java |
Adds XWiki 2.0 macro-content round-trip coverage. |
xwiki-rendering-syntaxes/xwiki-rendering-syntax-xwiki20/src/test/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxFreeStandingReferenceTest.java |
Tests full-syntax fallback for unsafe references. |
xwiki-rendering-syntaxes/xwiki-rendering-syntax-xwiki20/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxEscapeHandler.java |
Escapes complete curly-bracket runs. |
xwiki-rendering-syntaxes/xwiki-rendering-syntax-xwiki20/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxChainingRenderer.java |
Escapes parameters and ID macro values. |
xwiki-rendering-syntaxes/xwiki-rendering-syntax-xwiki20/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/reference/XWikiSyntaxResourceRenderer.java |
Escapes references and selects safe link syntax. |
xwiki-rendering-integration-tests/src/test/resources/wiki/link/links6.test |
Updates escaped-reference expectations. |
xwiki-rendering-integration-tests/src/test/resources/simple/macros/macro39.test |
Adds escaped link-reference coverage. |
xwiki-rendering-integration-tests/src/test/resources/simple/macros/macro38.test |
Adds escaped macro-parameter coverage. |
Review details
Suppressed comments (1)
xwiki-rendering-syntaxes/xwiki-rendering-syntax-xwiki20/src/main/java/org/xwiki/rendering/internal/renderer/xwiki20/XWikiSyntaxChainingRenderer.java:532
- This emits an inline macro through
print(...), so the escape printer does not apply itsprintInlineMacro()guard for a preceding delayed{. AnIdBlockimmediately following text{can therefore render as{{{id..., which the parser treats as verbatim syntax instead of a literal brace followed by the id macro. Use the inline-macro printing path here, asonMacro()does, so the preceding brace is escaped.
print(getMacroPrinter().renderMacro("id", Map.of("name", name), null, true));
- Files reviewed: 10/10 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…ntax in various attributes
* Print the id macro through the inline macro printing of the printer so
that a "{" printed just before it is escaped: otherwise the output
started with "{{{" and was parsed back as a verbatim block.
* Keep the bookkeeping of the regular printing - marking the first
element as rendered and closing pending empty formatting parameters -
by extracting it into printInlineMacro() instead of delegating to
onMacro(), whose inline branch skips both and would thus glue a
following paragraph to a standalone id macro.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ntax in various attributes * Replace deprecated methods in the changed code by their non-deprecated equivalents - the escape character "~" is already passed in the constructor. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
tmortagne
approved these changes
Sep 11, 2026
…ntax in various attributes * Clarify comment regarding macro content escaping.
💔 All backports failed
Manual backportTo create the backport manually run: Questions ?Please refer to the Backport tool documentation and see the Github Action logs for details |
michitux
added a commit
that referenced
this pull request
Sep 15, 2026
…ntax in various attributes (#433) * Escape the "{" runs of every value that the renderer serializes as-is: * (%...%) parameter values * link and image references, their parameters, and the xwiki/2.1 queryString and anchor reference parameters * the id macro name, which had no escaping at all and could also be broken by a quote in the name * Introduce XWikiSyntaxEscapeHandler#escapeCurlyBrackets as escaping helper that correctly escapes every character of a run of "{" instead of only the pairs: the previous two-pass "{{{"-then-"{{" replacement corrupted runs of four "{" and left a literal "{{" behind for runs of five, so it could still break out of a macro. * For free-standing references which cannot be escaped at all, fall back to the full [[...]] syntax when printing the reference free-standing would put a "{{" into the output, as that could close the macro the reference is serialized in. This is only about the macro syntax: the image and attachment tokens of the parser accept a "{{" and parse such a reference back unchanged, and where they don't - the URI token accepts no "{" at all - the reference is truncated just like by every other character that token rejects (a "}" or a "," for instance). That pre-existing limitation of free-standing references is not addressed here. * Correctly escape the reference of links that were initially freestanding when forced into the full syntax. * Expect [[~{~{macro}}]] in links6.test: the escaped form parses back to the very same reference while the previous output could badly interfere with outer macro syntax. * Print the id macro through the inline macro printing of the printer so that a "{" printed just before it is escaped: otherwise the output started with "{{{" and was parsed back as a verbatim block. * Keep the bookkeeping of the regular printing - marking the first element as rendered and closing pending empty formatting parameters - by extracting it into printInlineMacro() instead of delegating to onMacro(), whose inline branch skips both and would thus glue a following paragraph to a standalone id macro. * Replace deprecated methods in the changed code by their non-deprecated equivalents - the escape character "~" is already passed in the constructor. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> (cherry picked from commit 3352bcf)
michitux
added a commit
that referenced
this pull request
Sep 15, 2026
…ntax in various attributes (#433) * Escape the "{" runs of every value that the renderer serializes as-is: * (%...%) parameter values * link and image references, their parameters, and the xwiki/2.1 queryString and anchor reference parameters * the id macro name, which had no escaping at all and could also be broken by a quote in the name * Introduce XWikiSyntaxEscapeHandler#escapeCurlyBrackets as escaping helper that correctly escapes every character of a run of "{" instead of only the pairs: the previous two-pass "{{{"-then-"{{" replacement corrupted runs of four "{" and left a literal "{{" behind for runs of five, so it could still break out of a macro. * For free-standing references which cannot be escaped at all, fall back to the full [[...]] syntax when printing the reference free-standing would put a "{{" into the output, as that could close the macro the reference is serialized in. This is only about the macro syntax: the image and attachment tokens of the parser accept a "{{" and parse such a reference back unchanged, and where they don't - the URI token accepts no "{" at all - the reference is truncated just like by every other character that token rejects (a "}" or a "," for instance). That pre-existing limitation of free-standing references is not addressed here. * Correctly escape the reference of links that were initially freestanding when forced into the full syntax. * Expect [[~{~{macro}}]] in links6.test: the escaped form parses back to the very same reference while the previous output could badly interfere with outer macro syntax. * Print the id macro through the inline macro printing of the printer so that a "{" printed just before it is escaped: otherwise the output started with "{{{" and was parsed back as a verbatim block. * Keep the bookkeeping of the regular printing - marking the first element as rendered and closing pending empty formatting parameters - by extracting it into printInlineMacro() instead of delegating to onMacro(), whose inline branch skips both and would thus glue a following paragraph to a standalone id macro. * Replace deprecated methods in the changed code by their non-deprecated equivalents - the escape character "~" is already passed in the constructor. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> (cherry picked from commit 3352bcf)
michitux
added a commit
that referenced
this pull request
Sep 15, 2026
…ntax in various attributes (#433) * Escape the "{" runs of every value that the renderer serializes as-is: * (%...%) parameter values * link and image references, their parameters, and the xwiki/2.1 queryString and anchor reference parameters * the id macro name, which had no escaping at all and could also be broken by a quote in the name * Introduce XWikiSyntaxEscapeHandler#escapeCurlyBrackets as escaping helper that correctly escapes every character of a run of "{" instead of only the pairs: the previous two-pass "{{{"-then-"{{" replacement corrupted runs of four "{" and left a literal "{{" behind for runs of five, so it could still break out of a macro. * For free-standing references which cannot be escaped at all, fall back to the full [[...]] syntax when printing the reference free-standing would put a "{{" into the output, as that could close the macro the reference is serialized in. This is only about the macro syntax: the image and attachment tokens of the parser accept a "{{" and parse such a reference back unchanged, and where they don't - the URI token accepts no "{" at all - the reference is truncated just like by every other character that token rejects (a "}" or a "," for instance). That pre-existing limitation of free-standing references is not addressed here. * Correctly escape the reference of links that were initially freestanding when forced into the full syntax. * Expect [[~{~{macro}}]] in links6.test: the escaped form parses back to the very same reference while the previous output could badly interfere with outer macro syntax. * Print the id macro through the inline macro printing of the printer so that a "{" printed just before it is escaped: otherwise the output started with "{{{" and was parsed back as a verbatim block. * Keep the bookkeeping of the regular printing - marking the first element as rendered and closing pending empty formatting parameters - by extracting it into printInlineMacro() instead of delegating to onMacro(), whose inline branch skips both and would thus glue a following paragraph to a standalone id macro. * Replace deprecated methods in the changed code by their non-deprecated equivalents - the escape character "~" is already passed in the constructor. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> (cherry picked from commit 3352bcf)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Jira URL
https://jira.xwiki.org/browse/XRENDERING-815
Changes
Description
{{macro}}]] in links6.test: the escaped form parses back to the very same reference while the previous output could badly interfere with outer macro syntax.Clarifications
Screenshots & Video
No UI changes.
Executed Tests
Whole
xwiki-renderingwith quality profile.Expected merging strategy