Skip to content

Commit 662605d

Browse files
committed
Add - Pin the sanitize_key() collapse cases in state_compact().
Requested independently by both reviewers on the rate-table seam PR: the changelog cites a non-Latin state as the motivating case, but no provider row exercised one, so the behavior rested on reasoning rather than on a test. Adds five rows. Three collapse to empty outright (Cyrillic, CJK, a bare diacritic). Two collapse only partially -- 'IF' with a circumflex becomes 'F', 'AL' with a ring above becomes 'L' -- and those are the dangerous shape, because the result is a shorter but still perfectly plausible state code. That is exactly the duplication path this seam exists to close: the row is stored under the collapsed value and looked up under the raw one, so it can never be found again and a fresh row is inserted on every calculation. Expected values were read off WordPress's own sanitize_key() rather than derived by hand; the test's existing second assertion re-checks that agreement per row. All five fail against the pre-migration str_replace() implementation.
1 parent db19683 commit 662605d

1 file changed

Lines changed: 29 additions & 7 deletions

File tree

tests/php/Tax/test-address.php

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -834,17 +834,39 @@ public function test_state_compact_mirrors_core_storage_normalisation( $raw, $ex
834834
/**
835835
* Data provider for `test_state_compact_mirrors_core_storage_normalisation`.
836836
*
837+
* The non-ASCII rows are the ones the changelog's motivating case rests on, and they
838+
* are the reason the old `str_replace( ' ', '' )` lookup was unsafe rather than merely
839+
* incomplete. `sanitize_key()` drops every byte outside `[a-z0-9_-]`, so a state can
840+
* collapse to `''` outright (Cyrillic, CJK, a bare diacritic) or — worse — collapse
841+
* *partially* to a shorter ASCII string that is a perfectly plausible state code. The
842+
* partial cases are the duplication risk: the row is stored under the collapsed value
843+
* and searched for under the raw one, so it can never be found again and a fresh row
844+
* is inserted every calculation.
845+
*
846+
* Expected values are what WordPress's own `sanitize_key()` produces, read off the
847+
* function rather than reasoned about — the test's second assertion re-checks that
848+
* agreement on every row.
849+
*
837850
* @return array<string, array{0: string, 1: string}>
838851
*/
839852
public function state_compact_provider() {
840853
return array(
841-
'already canonical' => array( 'NY', 'NY' ),
842-
'lower case' => array( 'ny', 'NY' ),
843-
'internal space' => array( 'N Y', 'NY' ),
844-
'periods' => array( 'N.Y.', 'NY' ),
845-
'hyphen kept' => array( 'AB-12', 'AB-12' ),
846-
'digits kept' => array( 'A1', 'A1' ),
847-
'empty' => array( '', '' ),
854+
'already canonical' => array( 'NY', 'NY' ),
855+
'lower case' => array( 'ny', 'NY' ),
856+
'internal space' => array( 'N Y', 'NY' ),
857+
'periods' => array( 'N.Y.', 'NY' ),
858+
'hyphen kept' => array( 'AB-12', 'AB-12' ),
859+
'digits kept' => array( 'A1', 'A1' ),
860+
'empty' => array( '', '' ),
861+
862+
// Collapse to empty — nothing survives sanitize_key().
863+
'cyrillic collapses' => array( 'ЛЕН', '' ),
864+
'cjk collapses' => array( '东京', '' ),
865+
'bare diacritic collapses' => array( 'Ö', '' ),
866+
867+
// Partial collapse — the dangerous shape: a shorter, still-plausible code.
868+
'accented latin part-drops' => array( 'ÎF', 'F' ),
869+
'ring above part-drops' => array( 'ÅL', 'L' ),
848870
);
849871
}
850872

0 commit comments

Comments
 (0)