Skip to content

libc: setlocale must reject unavailable locales and return a name newlocale accepts - #1477

Open
gburd wants to merge 1 commit into
cloudius-systems:masterfrom
gburd:pr/setlocale-fix
Open

libc: setlocale must reject unavailable locales and return a name newlocale accepts#1477
gburd wants to merge 1 commit into
cloudius-systems:masterfrom
gburd:pr/setlocale-fix

Conversation

@gburd

@gburd gburd commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Problem

OSv has no on-disk locale database and provides only the C locale, but
setlocale() returned "C.UTF-8" unconditionally and ignored its arguments.
That is observably wrong for a portable application in two ways:

  1. A request for a locale OSv cannot provide (for example "en_US.UTF-8")
    must return NULL so the caller learns it is unavailable. The stub
    silently reported success for a locale that was never actually in effect.

  2. setlocale() must return a name that newlocale() will accept, because
    portable software round-trips the two. PostgreSQL derives a new database's
    default collation from setlocale() and feeds that name back into
    newlocale(). The stub returned "C.UTF-8", which OSv's newlocale()
    rejects, so a cluster initialized with LC_COLLATE=C nonetheless stamped
    every CREATE DATABASE with datcollate="C.UTF-8" and then could not open
    it (could not create locale "C.UTF-8": ENOENT). Any application that
    creates its own database at runtime was blocked; clusters whose locale was
    baked at initdb time happened to avoid it, which hid the bug.

Fix

Replace the stub with a small correct implementation: report the C locale
(which newlocale() accepts) and accept only the C-family names OSv can
actually provide ("", C, POSIX, C.UTF-8), failing any other request.
Character-set encoding (for example UTF8 in PostgreSQL) is independent of the
libc locale and is unaffected.

Testing

Built and booted; a stock PostgreSQL cluster on OSv can now CREATE DATABASE
and open the result, which previously failed with the ENOENT above.

…able name

OSv has no on-disk locale database and provides only the C locale, but its
setlocale() stub returned "C.UTF-8" unconditionally and ignored its
arguments. That is observably wrong in two ways:

  - A request for a locale OSv cannot provide (e.g. "en_US.UTF-8") must
    return NULL so the caller learns it is unavailable; the stub silently
    reported success for a locale that was never in effect.

  - setlocale() must return a name newlocale() will accept, because portable
    software round-trips the two. PostgreSQL derives a new database's default
    collation from setlocale() and feeds it back to newlocale(); the stub
    returned "C.UTF-8", which OSv's newlocale() rejects, so a cluster
    initialized with LC_COLLATE=C still stamped every CREATE DATABASE with
    datcollate="C.UTF-8" and then could not open it ("could not create
    locale \"C.UTF-8\": ENOENT"). Any application that creates its own
    database at runtime was blocked; initdb-time-baked clusters happened to
    avoid it, which hid the bug.

Return the C locale (which newlocale() accepts) and accept only the C-family
names OSv can provide ("", "C", "POSIX", "C.UTF-8"), failing others.
Character-set encoding (e.g. UTF8 in PostgreSQL) is independent of the libc
locale and is unaffected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant