WordPress.org

Make WordPress Core

Opened 6 weeks ago

Closed 4 weeks ago

#53936 closed defect (bug) (fixed)

Output of serialize_block_attributes does not match equivalent Gutenberg function

Reported by: kevinfodness Owned by: desrosj
Milestone: 5.8.1 Priority: normal
Severity: normal Version: 5.3.1
Component: Editor Keywords: has-patch has-unit-tests commit fixed-major
Focuses: Cc:

Description

In wp-includes/blocks.php, the serialize_block_attributes function runs json_encode with no options, which results in encoding all unicode elements and slashes. This behavior differs from Gutenberg's attribute serializer, which uses JSON.stringify, for which the default behavior does not encode slashes or unicode characters. In order to ensure that the two attribute serialization functions return the same output, I recommend using the options JSON_UNESCAPED_UNICODE and JSON_UNESCAPED_SLASHES in the PHP function.

This example illustrates the differences in output between the two functions:

<?php
serialize_block_attributes( [ 'product' => 'Mike & Ike: €1.00 / 3 for €2.00' ] );
// {"product":"Mike \u0026 Ike: \u20ac1.00 \/ 3 for \u20ac2.00"}

Versus JavaScript:

serializeAttributes({ product: 'Mike & Ike: €1.00 / 3 for €2.00' });
// {"product":"Mike \u0026 Ike: €1.00 / 3 for €2.00"}

In the PHP example, the forward slash and the Euro symbol are both escaped, but in JavaScript, they aren't.

If we modify the flags in the serialize_block_attributes as follows:

$encoded_attributes = json_encode( $block_attributes, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );

Then the output matches what we get from the JavaScript function.

I'll get working on a patch that both exposes this issue via a unit test and resolves it in the manner I proposed above, and I'll attach it here when I'm done.

Related: Is there a reason why we are using json_encode here rather than wp_json_encode? As near as I can tell, this is the only location in WordPress core source code that uses json_encode other than the wp_json_encode function itself. Assuming this is in error, I'll make that change in my patch as well.

Change History (8)

#1 in reply to: ↑ description @SergeyBiryukov
6 weeks ago

  • Component changed from General to Editor

Hi there, welcome to WordPress Trac! Thanks for a detailed bug report.

Replying to kevinfodness:

Related: Is there a reason why we are using json_encode here rather than wp_json_encode? As near as I can tell, this is the only location in WordPress core source code that uses json_encode other than the wp_json_encode function itself. Assuming this is in error, I'll make that change in my patch as well.

Good catch, this seems like an oversight. Per [30055] / #28786, any json_encode() calls in core should indeed be converted to wp_json_encode(), as the former can fail if the data contains any non UTF-8 characters.

This ticket was mentioned in PR #1594 on WordPress/wordpress-develop by kevinfodness.


6 weeks ago

  • Keywords has-patch has-unit-tests added

The block attribute serialization function in PHP does not produce equivalent output to the JavaScript function in the Gutenberg codebase. Specifically, unicode characters and slashes are escaped in PHP whereas they are not in JavaScript. This update exposes the bug via a unit test and fixes it in the serialization function. Additionally, it replaces json_encode with wp_json_encode.

Trac ticket: https://core.trac.wordpress.org/ticket/53936

#3 @desrosj
6 weeks ago

  • Milestone changed from Awaiting Review to 5.8.1

This looks like something that could be included in 5.8.1. Moving to the milestone for consideration.

#4 @desrosj
5 weeks ago

  • Keywords commit added

Thanks for this fix, @kevinfodness! I discussed this briefly with @TimothyBlynJacobs in Slack, and he recalled that this reminded him of #40560. But, we arrived at the decision that it probably makes sense to land this.

#5 @desrosj
5 weeks ago

  • Version set to 5.3.1

#6 @desrosj
5 weeks ago

  • Owner set to desrosj
  • Resolution set to fixed
  • Status changed from new to closed

In 51674:

Editor: Ensure block attribute serialization in PHP matches the JavaScript equivalent.

The serializeAttributes() function in JavaScript uses JSON.stringify, which does not encode slashes and unicode characters by default. This resulted in the PHP serialization through json_encode() producing different results.

This also switches from json_encode() to wp_json_encode() to prevent failures when any non UTF-8 characters are included.

Props kevinfodness, SergeyBiryukov, timothyblynjacobs.
Fixes #53936.

#7 @desrosj
5 weeks ago

  • Keywords fixed-major added
  • Resolution fixed deleted
  • Status changed from closed to reopened

Reopening to backport.

#8 @desrosj
4 weeks ago

  • Resolution set to fixed
  • Status changed from reopened to closed

In 51681:

Editor: Ensure block attribute serialization in PHP matches the JavaScript equivalent.

The serializeAttributes() function in JavaScript uses JSON.stringify, which does not encode slashes and unicode characters by default. This resulted in the PHP serialization through json_encode() producing different results.

This also switches from json_encode() to wp_json_encode() to prevent failures when any non UTF-8 characters are included.

Props kevinfodness, SergeyBiryukov, timothyblynjacobs.
Merges [51674] to the 5.8 branch.
Fixes #53936.

Note: See TracTickets for help on using tickets.