Opened 4 years ago
Last modified 11 days ago
#55776 reopened defect (bug)
sprintf missformat fatal error php 8
| Reported by: | ognjanovic | Owned by: | |
|---|---|---|---|
| Priority: | normal | Milestone: | |
| Component: | General | Version: | |
| Severity: | normal | Keywords: | php8 |
| Cc: | Focuses: | administration |
Description
There is a fatal error generated in admin-header.php on line 62
$screen_title = sprintf( /* translators: Editor admin screen title. 1: "Edit item" text for the post type, 2: Post title. */ __( '%1$s “%2$s”' ), $post_type_obj->labels->edit_item, $post_title );
This part
__( '%1$s “%2$s”' )
There should be a space after %2$s in order to work in php 8.0.14 (the only version I tested in).
Change History (8)
#1
follow-up:
↓ 2
@
4 years ago
- Focuses coding-standards removed
- Keywords reporter-feedback added; needs-patch removed
#2
in reply to: ↑ 1
@
4 years ago
Replying to johnbillion:
Thanks for the report @ognjanovic. Can you let us know the full fatal error message text, file name, line number, etc, please?
Sure. Trying to edit any post or page you’ll get this error
2022/05/18 11:35:51 [error] 50#0: *5269743 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught ValueError: Argument number specifier must be greater than zero and less than 2147483647 in /var/www/html/wp-admin/admin-header.php:62
Stack trace:
#0 /var/www/html/wp-admin/admin-header.php(62): sprintf()
#1 /var/www/html/wp-admin/edit-form-advanced.php(425): require_once('...')
#2 /var/www/html/wp-admin/post.php(206): require('...')
#3 {main}
thrown in /var/www/html/wp-admin/admin-header.php on line 62" while reading response header from upstream, client: 10.130.10.1, server: mpn.gov.rs, request: "GET /wp-admin/post.php?post=646&action=edit HTTP/1.1", upstream: "fastcgi://unix:/run/php-fpm/www.sock:", host: "hidden.url", referrer: "https://hidden.url/wp-admin/edit.php?post_type=cpt"
#3
@
4 years ago
- Keywords reporter-feedback removed
- Milestone Awaiting Review
- Resolution → invalid
- Status new → closed
- Version 5.9.3
Hello @ognjanovic, I'm assuming you're using WordPress with the Serbian translation? There was an error in the translation which was fixed a while ago, see https://translate.wordpress.org/projects/wp/dev/admin/sr/default/?filters%5Bstatus%5D=either&filters%5Boriginal_id%5D=12959676&sort%5Bby%5D=translation_date_added&sort%5Bhow%5D=asc. Please check wp-admin/update-core.php for any translation updates.
Marking as invalid since it's not a bug in core.
Related: #meta6256
#4
@
4 years ago
- Keywords php8 added
I can confirm @ocean90's assessment. Also see: https://3v4l.org/88qOj which shows that the code in Core is absolutely fine PHP cross-version. Which automatically points the finger at a translation being wrong.
This ticket was mentioned in Slack in #buddypress by imath. View the logs.
3 years ago
#6
@
5 weeks ago
- Resolution invalid
- Status closed → reopened
Hi,
I think there is still a broader problem worth considering: wrong translation input should not be able to cause a fatal error in WordPress.
This happened to my plugin today:
https://wordpress.org/support/topic/critical-error-on-many-sites/
https://wordpress.org/support/topic/fatal-error-on-wp-admin-updates-page/
https://wordpress.org/support/topic/critical-error-wordpress-5/
https://wordpress.org/support/topic/gtranslate-fatal-error-in-wordpress-admin-caused-by-broken-spanish-translation/
The current WordPress internationalization guidelines recommend using printf() and sprintf() for variables in translated strings, including numbered placeholders for argument swapping: https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/
It may be useful for WordPress to provide safer wrappers, for example:
wp_safe_sprintf()
wp_safe_printf()
These could catch formatting errors, trigger a warning or notice for developers/translators, and fall back to the original untranslated source string instead of allowing a fatal error.
Thanks!
#7
@
3 weeks ago
Hi,
The root cause is that sprintf()/printf() in gtranslate.php are called directly on translated strings (esc_html(...)). When a translation pack is malformed — e.g. the corrupted gtranslate-es_ES pack where %1$s became %1$t (%1$stráfico → %1$tráfico) — PHP 8 throws Uncaught ValueError: Unknown format specifier "t" and the whole site + wp-admin go down (the fatal reported at gtranslate.php:2090).
Deleting the .mo/.po/.l10n.php files works as a workaround, but the plugin stays vulnerable to any broken translation pack. A more robust fix is to make the plugin never let a malformed format string escalate into a fatal error. What I did in our copy:
Added three small helper functions (guarded with function_exists): gt_safe_vsprintf($format, array $args), gt_safe_sprintf($format, ...$args) and gt_safe_printf($format, ...$args).
gt_safe_vsprintf() runs vsprintf() inside a try/catch (\Throwable). On failure it normalizes every %n$X/%X token to %s, pads/trims the argument list to match, and retries; as a last resort it strips the specifiers. So it can never emit a fatal error.
Replaced the direct sprintf(...) / printf(...) calls that wrap translatable strings with gt_safe_sprintf(...) / gt_safe_printf(...) (the admin-notice and settings-page strings, including the one at what was line ~2090).
For a healthy translation the output is byte-for-byte identical to the current code; only a broken format string is caught and degraded gracefully instead of taking the site down.
Would you consider hardening these calls (or the translated format strings) in the next release? Thanks for the plugin!
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
Thanks for the report @ognjanovic. Can you let us know the full fatal error message text, file name, line number, etc, please?