HTML API: set_modifiable_text should fail on foregin element tags#11083
HTML API: set_modifiable_text should fail on foregin element tags#11083sirreal wants to merge 16 commits intoWordPress:trunkfrom
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
There was a problem hiding this comment.
Pull request overview
This PR fixes an HTML API edge case where set_modifiable_text() could incorrectly apply special “atomic element” handling to foreign (SVG/MathML) elements whose tag names match atomic HTML elements, by ensuring the special handling only runs in the HTML namespace.
Changes:
- Restrict
WP_HTML_Tag_Processor::set_modifiable_text()atomic-element handling to the HTML namespace. - Add PHPUnit coverage to ensure
set_modifiable_text()rejects non-atomic HTML tags and atomic-like foreign tags (SVG/MathML) without mutating the input HTML. - Add parallel coverage in both
WP_HTML_ProcessorandWP_HTML_Tag_Processortest suites.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/wp-includes/html-api/class-wp-html-tag-processor.php |
Adds an HTML-namespace guard before applying atomic-tag modifiable-text logic. |
tests/phpunit/tests/html-api/wpHtmlProcessorModifiableText.php |
Adds fragment-level tests ensuring set_modifiable_text() fails (and doesn’t mutate HTML) for non-atomic/foreign tags. |
tests/phpunit/tests/html-api/wpHtmlTagProcessorModifiableText.php |
Adds tag-processor tests ensuring set_modifiable_text() fails for non-atomic and foreign atomic-like tags. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| string $parsing_namespace, | ||
| string $expected_tag | ||
| ) { | ||
| $processor = new WP_HTML_Tag_Processor( $html ); |
There was a problem hiding this comment.
this is ultimately a test of the Tag Processor and its behavior, no? as in, a failure here is a bug, but a failure in the HTML Processor is a bug in detecting namespace changes.
Does it make sense to run the test in both places? If so, wouldn’t it be quite easy for the tests to diverge given that they are in separate files?
If we want to ensure that the behavior is locked, why not run both classes from this same test runner? Since we have tests already asserting that the HTML Processor detects the namespace changes, we should only need to test the modifiable text behavior here, and therefore we should be fine reading the namespace from the HTML Processor rather than supplying it.
There was a problem hiding this comment.
I don't know what you have in mind here, perhaps you could clarify. I'm open to changing or moving things, there is some duplication between these tests.
I will elaborate that the HTML Processor tests have added value. Subtle issues can appear in the interaction between the "smart" HTML processor and the "syntax-only" tag processor.
For example, this change appears equivalent, but it would make the HTML processor tests fail, detecting an issue with svg:TITLE elements:
diff --git c/src/wp-includes/html-api/class-wp-html-tag-processor.php i/src/wp-includes/html-api/class-wp-html-tag-processor.php
index d544f0f49b..cba78fdb51 100644
--- c/src/wp-includes/html-api/class-wp-html-tag-processor.php
+++ i/src/wp-includes/html-api/class-wp-html-tag-processor.php
@@ -3813,7 +3813,7 @@ class WP_HTML_Tag_Processor {
*/
if (
self::STATE_MATCHED_TAG !== $this->parser_state ||
- 'html' !== $this->get_namespace()
+ 'html' !== $this->parsing_namespace
) {
return false;
}That's because svg:title is an HTML integration point. When the svg:title element is put on the stack of open elements, the parsing namespace changes to HTML (this is correct, its children will be HTML elements), but the element's namespace is svg. It's important to use $this->get_namespace() to detect the current namespace and not the namespace to be used for ongoing parsing.
There was a problem hiding this comment.
right, but wouldn’t or shouldn’t this test case be caught by those tests covering the integration point logic, and not slipped under the rug in a seemingly unrelated test?
on the contrary, if we introduced this bug, I would want that to cause a failure in detecting the svg:TITLE namespace, not in some set_modifiable_text() assertion which is testing html:TITLE
There was a problem hiding this comment.
The bug in the diff I shared would be in the implementation of the ::set_modifiable_text() function. I didn't introduce that bug, but could have. I had to consider carefully which was correct and whether there was a difference and I'm intimately familiar with this code.
I'm not sure how else that particular issue could be detected. It's not a problem in any of the other systems. It would be a bug with ::set_modifiable_text(). It would be easy to introduce by assuming that a property check can be trivially swapped for a getter as a micro-optimization. It can't, that would be a mistake.
tests/phpunit/tests/html-api/wpHtmlTagProcessorModifiableText.php
Outdated
Show resolved
Hide resolved
tests/phpunit/tests/html-api/wpHtmlTagProcessorModifiableText.php
Outdated
Show resolved
Hide resolved
tests/phpunit/tests/html-api/wpHtmlTagProcessorModifiableText.php
Outdated
Show resolved
Hide resolved
|
I see my suggestions would also apply to r61754. |
Co-authored-by: Weston Ruter <westonruter@gmail.com>
Co-authored-by: Weston Ruter <westonruter@gmail.com>
Improve some test types from [61754]
| string $target_tag | ||
| ): void { | ||
| $processor = WP_HTML_Processor::create_fragment( $html ); | ||
| $this->assertInstanceOf( WP_HTML_Tag_Processor::class, $processor ); |
There was a problem hiding this comment.
I’ve been trying to leave helpful notes to people for cases like this where the failure should be unrelated to the unit under test. This is not meant to assert behaviors about creating Tag Processor.
$this->assertInstanceOf( …, $processor, 'Failed to initialize HTML Processor: check test setup.' );on that note, why are we asserting that the HTML Processor is a Tag Processor?
There was a problem hiding this comment.
In a few places I've used assert() to differentiate between test invariants and the unit under test. I don't think that's a common pattern but I do think it has some merits.
I've updated the test to be a non-null assertion with an descriptive message.
The method should only apply to special "atomic" HTML tags like `SCRIPT` or `TEXTAREA`. `::set_modifiable_text()` should not apply to tags with the same name in other namespaces. Developed in #11083. Props jonsurrell, dmsnell, westonruter. Fixes #64751. git-svn-id: https://develop.svn.wordpress.org/trunk@61796 602fd350-edb4-49c9-b593-d223f7449a82
The method should only apply to special "atomic" HTML tags like `SCRIPT` or `TEXTAREA`. `::set_modifiable_text()` should not apply to tags with the same name in other namespaces. Developed in WordPress/wordpress-develop#11083. Props jonsurrell, dmsnell, westonruter. Fixes #64751. Built from https://develop.svn.wordpress.org/trunk@61796 git-svn-id: http://core.svn.wordpress.org/trunk@61102 1a063a9b-81f0-0310-95a4-ce76da25c4cd
Ensure the the HTML API does not attempt to set modifiable text on a foreign element tag. This could happen in foreign content when the tag name matches a special "atomic" HTML element, like
SCRIPTorTEXTAREA.Trac ticket: https://core.trac.wordpress.org/ticket/64751
Use of AI Tools
AI assisted with the creation of tests, as well as expanding and improving the base test set.
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.