Zurück zu Cases
2023 · 6 Wochen · Core Contributor

Open Source / PostgreSQL

PostgresOpen SourceC

// problem

Problem

UTF-16-Surrogate-Paare wurden in bestimmten Locales nicht korrekt verglichen. Das führte zu falschen Sortierreihenfolgen in japanischen und koreanischen Texten. Vier Enterprise-Kunden mit je >1M Zeilen betroffen.

// approach

Approach

Root-Cause-Analyse im PostgreSQL-C-Codebase. Der Bug lag in pg_collate.c — die Surrogate-Range-Detection fehlte komplett. Entwicklung eines Patches mit umfassender Test-Suite. Review über pgsql-hackers Mailingliste mit 3 Iterations-Runden.

// code

pg_collate.c — Diff
static int
pg_strncoll_utf8(const char *s1, size_t len1,
                  const char *s2, size_t len2,
                  pg_locale_t locale)
{
    /*
     * Handle UTF-16 surrogate pairs correctly.
     * Previously, surrogates in the range
     * U+D800..U+DFFF were compared byte-by-byte,
     * producing incorrect sort orders.
     */
    const char *p1 = s1;
    const char *p2 = s2;

    while (p1 < s1 + len1 && p2 < s2 + len2)
    {
        if (IS_UTF16_SURROGATE_FIRST(*p1) &&
            IS_UTF16_SURROGATE_SECOND(*(p1+1)))
        {
            /* Compare full surrogate pair */
            int result = compare_surrogate_pair(
                p1, p2);
            if (result != 0)
                return result;
            p1 += 2; p2 += 2;
            continue;
        }
        p1++; p2++;
    }

    return ucol_strcollUTF8(locale->ucol,
                              s1, len1, s2, len2,
                              &status);
}

// outcome

Ergebnis

Patch in PostgreSQL 16.2 gemerged

4 Production-Incidents bei Enterprise-Kunden behoben

Test-Coverage für UTF-16-Surrogate-Vergleiche ergänzt

PostgreSQL Core Contributor Status erhalten