Opened 3 weeks ago
Closed 2 days ago
#66106 closed defect (bug) (fixed)
get_locale(), get_user_locale() and determine_locale() can return a non-string
| Reported by: | jonsurrell | Owned by: | jonsurrell |
|---|---|---|---|
| Priority: | normal | Milestone: | 7.2 |
| Component: | I18N | Version: | |
| Severity: | normal | Keywords: | has-patch has-unit-tests commit |
| Cc: | Focuses: |
Description (last modified by )
get_locale(), get_user_locale() and determine_locale() can return a non-string values. All three functions are documented @return string, but they read from untyped data sources that may be invalid.
Once an unexpected value gets through, the first just-in-time translation of an unloaded text domain reaches WP_Textdomain_Registry::set(), which uses the locale as an array key: TypeError: Cannot access offset of type array on array.
This is not theoretical, it was discovered from fatal errors observed in production environments.
Change History (9)
This ticket was mentioned in PR #13335 on WordPress/wordpress-develop by @jonsurrell.
3 weeks ago
#2
- Keywords has-patch has-unit-tests added
@jonsurrell commented on PR #13335:
3 weeks ago
#3
@josephscott This is ready for review if you'd like to take a look.
#4
@
3 weeks ago
This is not theoretical, it was discovered from fatal errors observed in production environments.
I'm curious as to the themes/plugins responsible for these errors. Clearly they are doing it wrong. Is there a better way to let them know they're doing it wrong besides what static analysis would have told them?
#5
@
3 weeks ago
I agree, I'd like to know how the bad data enters and address it there. Unfortunately, it's hard to know since this data is often stored or cached and the error only manifests in these fatals.
@josephscott commented on PR #13335:
3 weeks ago
#6
I think the changes look good. One thing that this PR changes is that some filters will no longer fire on the invalid values. From my point of view, that is the right move - there are likely many filters out there that don't check the values first. I bring it up as something that might be worth noting.
Now that I've written that out, I expect that type of change to happen in various places. Perhaps it is worth a broader single callout instead of adding it to code comments every where.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
Prevent non-string locale values from causing a
TypeErrorduring just-in-time translation. Arrays can come from stored options, user meta, globals, filters, or requests such aswp-login.php?wp_lang[]=de_DE; the existing truthiness checks accept them.Add
is_string()checks toget_locale(),get_user_locale()anddetermine_locale(). Invalid values use the existing fallbacks:en_USfor the site locale,get_locale()for the user or request locale, and the unfiltered locale for invalid filter results. Empty globals and emptylocaleordetermine_localefilter results now use these fallbacks too. Locale string syntax is unchanged.Writers are unchanged:
wp_insert_user(),meta_inputand direct metadata writes can still store non-strings, so the getters validate on read.Adds regression tests for stored values, globals, filters and request parameters, including translation calls with array locales.
Trac ticket: https://core.trac.wordpress.org/ticket/66106
## Use of AI Tools
AI assistance: Yes
Tools: Claude Code (Claude Opus 5, Claude Fable 5.1), Codex
Used for: Investigation, implementation, tests, review and description. Codex revised the description.