Problem/Motivation
When you display a config diff on admin/config/development/configuration/sync/diff/ , or make a page in a module that uses the \Drupal\Core\Diff\DiffFormatter class to display a diff, you will see a lot of double-escaped entities displayed on the page. (Note: this was originally #2314513: Add test coverage for DiffFormatter not double escaping but that has been marked as a duplicate of this issue.)
DiffFormatter also is generating the double-escaped nbsp characters in two methods:
protected function contextLine($line) {
return array(
' ',
array(
'data' => $line,
'class' => 'diff-context',
),
);
}
protected function emptyLine() {
return array(
' ',
' ',
);
}
And for some reason they are being check_plained.
There is another problem with the SafeMarkup from DIffFormatter as well (which was the original intent of this issue): DiffFormatter uses the \Drupal\Component\Diff\WordLevelFormatter class, which in turn uses \Drupal\Component\Diff\Engine\HWLDFWordAccumulator. This class has a line in its HWLDFWordAccumulator::_flushLine() method that says:
array_push($this->lines, SafeMarkup::set($this->line));
It is unlikely that this is the correct place to do SafeMarkup. Probably any SafeMarkup calls should be higher-level.
Proposed resolution
TBD
Remaining tasks
Code fix and tests.
There is a proposed test for this in comment #5, and an issue marked as duplicate also has a test specifically for the config diff display, see patch on #2314513: Add test coverage for DiffFormatter not double escaping .
User interface changes
Config diffs and other diffs using DiffFormatter will not have double-escaped entities in them.
API changes
TBD, probably not.
| Comment | File | Size | Author |
|---|---|---|---|
| #19 | Screen Shot 2015-06-07 at 12.16.23 PM.png | 375.11 KB | peezy |
| #17 | document_use_of-2280963-14_0.patch | 1.43 KB | chrisfromredfin |
| #15 | document_use_of-2280963-14.patch | 1.43 KB | chrisfromredfin |
| #13 | safemarkup-in-hwldfwordaccumulator-2280963-13.patch | 916 bytes | mlncn |
Comments
Comment #1
seantwalshComment #2
xjmComment #3
xjmComment #4
jibranComment #5
jhodgdonNote that #2314513: Add test coverage for DiffFormatter not double escaping is set as a duplicate of this issue.
So I'm assuming that this issue is about the
entries that are showing if you use the \Drupal\Core\Diff\DiffFormatter class.These are coming from two places:
(1)
(2)
The only use of this class in Core is I think in the Config system to make diffs. I am also using it for this purpose in my contrib/sandbox module https://www.drupal.org/sandbox/jhodgdon/2391835
If someone wants to make a test for this problem, while avoiding Config, here are some ideas:
a) Make two arrays of lines of text, $a and $b. For instance you could do:
b) Call
to compute the differences between the arrays.
c) To make this into a table of differences for display:
where diffFormatter comes from:
in the create() function.
d) Display this table on a page, or run it through drupal_render() or whatever it's called these days.
Hopefully that will be enough for someone to go on if they want to make a test for this.
Comment #6
jhodgdonAnd I apologize if #5 is not what this issue is about. chx marked that other issue as a duplicate so I assumed so. If not we should unmark the other issue as not a duplicate and go from there and fix that issue.
Comment #7
larowlanthe other issue has a test too
Comment #8
jhodgdonYes. The other issue has a test that verifies that admin/config/development/configuration/sync/diff/ does not have
 showing up on it. My suggestion in #5 is to make a more generic test that specifically tests DiffFormatter and does not depend on Config Manager module.So... This title and summary were not exactly illuminating to me. So I did some research, and updated the issue summary and title.
I am still not sure that #2314513: Add test coverage for DiffFormatter not double escaping is a duplicate of this issue. This one was filed about the use of SafeMarkup buried deep within the HWLDFWordAccumulator class. Which is likely a problem, but I don't think it is the cause of the double-escaped nbsp entities we are seeing in config diffs.
Updating summary and title. Hopefully it will be clearer.
Comment #9
jhodgdonMy sandbox Config Revert module, which uses the DiffFormatter class, is no longer showing the nbsp characters double-escaped. So, the duplicate issue may have vanished. I haven't looked at the code to see what changed, and I'm not sure that Core is even using this class any more?
Comment #10
andypostFirst half of problem was fixed in #2318081: remove ' ' from Drupal/Core/Diff/DiffFormatter
So now it's harder to test what is autoescaped
Comment #11
xjmComment #12
xjmRetitling since the other bug was resolved.
Comment #13
mlncn commentedAs predicted and then noted by jhodgdon, and confirmed by andypost, this use of SafeMarkup was not the cause of the escaping issues. Further, it is a correct use of SafeMarkup (in that what it is marking is undeniably safe) and turning the incremental creation of a diff line into a template or even an inline template would force these onto WordLevelDiff and upstream.
Comment #14
joelpittetI think we can rework the lines above to have them safe when they get here.
Comment #15
chrisfromredfinComment #17
chrisfromredfinwoops!
Comment #18
joelpittetThanks this looks great. Needs some manual testing but otherwise it should be good.
Comment #19
peezy commentedThe patch has passed manual testing. In the screenshot below, the upper image shows CMI's diff markup before applying the path; the lower image shows the identical markup after applying the patch.

Manual testing steps
Do these steps both with HEAD and with the patch applied:
alert('XSS');
and ensure that it is sanitized.
Comment #20
joelpittetThank you both!
Comment #21
joelpittetThank you both!
Comment #22
alexpottAs sad as it is to have a dependency on SafeMarkup in the Diff component I can't see a way around it. Especially considering we're potentially mixing markup with things that need to be escaped at this point. I tested this by exporting configuration and change the list of allowed tags in
filter.format.basic_html.yml. It works nicely.This is a non disruptive change that removes a call to SafeMarkup::set() - therefore permitted during beta. Committed 53065cb and pushed to 8.0.x. Thanks!
Comment #24
xjmThe summary indicates that #2314513: Add test coverage for DiffFormatter not double escaping had a test for this, but the test never got added to this patch. I've reopened #2314513: Add test coverage for DiffFormatter not double escaping to look into adding it.
Comment #25
xjmAlso posted a small followup: #2509448: Further refactor use of SafeMarkup in HWLDFWordAccumulator.