Skip to content

Commit 10453ab

Browse files
sirrealdmsnellMamadukaskorasaurusyouknowriad
authored
Allow block attribute strings to terminate in "\" character (WordPress#71291)
Fix an issue in the block editor where attributes that terminate in the \ character are mis-encoded and cause block attributes to be lost. This change encodes `\` characters with their Unicode escape sequence `\u005c` instead of their escaped form `\\`. This makes the replacement of escaped double quotes `\"` much simpler because the preceding `\` character must be the escape character for the quote and an escaped character itself. Escaping of `\"` was originally introduced in WordPress#6619 to address an issue where `wp_kses_stripslashes()` would replace escaped double quotes `\"` with plain quotes `"` and break JSON syntax (`{"str":"\""}` becomes `{"str":"""}`). There is a companion ticket for WordPress Core: https://core.trac.wordpress.org/ticket/63917 And an associated PR to apply the same updated JSON encoding: WordPress/wordpress-develop#9558 See a related ticket about `wp_kses_stripslashes()` and its purpose today: https://core.trac.wordpress.org/ticket/63881 --- Unlinked contributors: ehti, Alexius08. Co-authored-by: sirreal <jonsurrell@git.wordpress.org> Co-authored-by: dmsnell <dmsnell@git.wordpress.org> Co-authored-by: Mamaduka <mamaduka@git.wordpress.org> Co-authored-by: skorasaurus <skorasaurus@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
1 parent 60986cd commit 10453ab

File tree

2 files changed

+24
-10
lines changed

2 files changed

+24
-10
lines changed

packages/blocks/src/api/serializer.js

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -281,19 +281,21 @@ export function getCommentAttributes( blockType, attributes ) {
281281
export function serializeAttributes( attributes ) {
282282
return (
283283
JSON.stringify( attributes )
284+
// Replace escaped `\` characters with the unicode escape sequence.
285+
.replaceAll( '\\\\', '\\u005c' )
286+
284287
// Don't break HTML comments.
285-
.replace( /--/g, '\\u002d\\u002d' )
288+
.replaceAll( '--', '\\u002d\\u002d' )
286289

287290
// Don't break non-standard-compliant tools.
288-
.replace( /</g, '\\u003c' )
289-
.replace( />/g, '\\u003e' )
290-
.replace( /&/g, '\\u0026' )
291-
292-
// Bypass server stripslashes behavior which would unescape stringify's
293-
// escaping of quotation mark.
294-
//
295-
// See: https://developer.wordpress.org/reference/functions/wp_kses_stripslashes/
296-
.replace( /\\"/g, '\\u0022' )
291+
.replaceAll( '<', '\\u003c' )
292+
.replaceAll( '>', '\\u003e' )
293+
.replaceAll( '&', '\\u0026' )
294+
295+
// Replace escaped quotes (`\"`) to prevent problems with wp_kses_stripsplashes.
296+
// This simple replacement is safe because `\\` has already been replaced.
297+
// `\"` is not a JSON string quote like `"\\"`.
298+
.replaceAll( '\\"', '\\u0022' )
297299
);
298300
}
299301

packages/blocks/src/api/test/serializer.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,18 @@ describe( 'block serializer', () => {
204204
'{"a":"\\u0022 and \\u0022"}'
205205
);
206206
} );
207+
208+
it( 'should handle backslash and quote combinations', () => {
209+
const orig = {
210+
bs: '\\',
211+
bsQuote: '\\"',
212+
bsQuoteBs: '\\"\\',
213+
};
214+
expect( JSON.parse( serializeAttributes( orig ) ) ).toEqual( orig );
215+
expect( serializeAttributes( orig ) ).toBe(
216+
'{"bs":"\\u005c","bsQuote":"\\u005c\\u0022","bsQuoteBs":"\\u005c\\u0022\\u005c"}'
217+
);
218+
} );
207219
} );
208220

209221
describe( 'getCommentDelimitedContent()', () => {

0 commit comments

Comments
 (0)