Re: [PATCH] initdb: Treat empty -U argument as unset username - Mailing list pgsql-hackers

From Jianghua Yang
Subject Re: [PATCH] initdb: Treat empty -U argument as unset username
Date
Msg-id CAAZLFmQ5Ckdb1WSp0wkVczk2rde1j-2PdrmwPNywG-XO5ph+aQ@mail.gmail.com
Whole thread Raw
In response to Re: [PATCH] initdb: Treat empty -U argument as unset username  (Peter Eisentraut <peter@eisentraut.org>)
List pgsql-hackers
Hi Peter,

Thanks for your detailed analysis. I appreciate you digging deeper into the root cause.

For this patch, I'd like to keep the changes to `initdb` minimal and focused on rejecting empty usernames, as that seems to be the consensus from the previous discussion.

I'll be happy to discuss the `getid()` and `aclitem` parsing behavior in a separate thread.

Best regards,
Jianghua Yang


Peter Eisentraut <peter@eisentraut.org> 于2025年7月2日周三 07:39写道:
On 02.07.25 04:55, Jianghua Yang wrote:
> While working with `initdb`, I noticed that passing an empty string to
> the `-U` option (e.g., `initdb -U ''`) causes it to fail with a
> misleading error:
>
> performing post-bootstrap initialization ... 2025-07-01 19:48:42.006 PDT
> [14888] FATAL:role """ does not exist at character 72
>
> 2025-07-01 19:48:42.006 PDT [14888] STATEMENT:
>
> UPDATE pg_class SET relacl = (SELECT array_agg(a.acl) FROM(SELECT
> E'=r/""' as acl UNION SELECT unnest(pg_catalog.acldefault(CASE WHEN
> relkind = 'S' THEN 's'ELSE 'r' END::"char",10::oid)) ) as a) WHERE
> relkind IN ('r', 'v', 'm', 'S')AND relacl IS NULL;
>
> This happens because `initdb` accepts the empty string as a valid role
> name and attempts to use it as the database superuser, which is not
> intended and fails during bootstrap SQL.

I'll start by saying, of course an empty user name isn't going to work,
so we should reject it.

But let's dig a little deeper into why it fails.  Observe the error:

     FATAL:role """ does not exist at character 72

It thinks that the role name is `"` (a sole double-quote, not empty!).
Why is that?

This error comes from the literal

    E'=r/""'

interpreted as an aclitem value.  The aclitem parsing ends up in getid()
in src/backend/utils/adt/acl.c, which thinks that an input string
consisting entirely of "" is an escaped double quote.

Maybe it's worth fixing that, and making putid() also print empty user
names correspondingly.

Alternatively, it's the fault of initdb that it constructs aclitem
values that don't follow the aclitem-specific quoting rules.

Another thought is, if we don't allow zero-length names, shouldn't
namein() reject empty input strings?  Then this whole thing would fail
as postgres.bki is being loaded.  (This is more hypothetical, since this
appears to break a number of other things.)

All of this is to say, it's worth looking at the actual cause and think
about if there are related problems, maybe other name patterns that we
don't handle well, instead of just papering over it at the top level.

pgsql-hackers by date:

Previous
From: Fujii Masao
Date:
Subject: Re: Add progressive backoff to XactLockTableWait functions
Next
From: Tom Lane
Date:
Subject: Re: Allow the "operand" input of width_bucket() to be NaN