| From: | PG Bug reporting form <noreply(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Cc: | 1548140642(at)qq(dot)com |
| Subject: | BUG #19866: acldefault() emits invalid UTF-8 for a high-bit "char" value |
| Date: | 2026-11-11 05:39:16 |
| Message-ID: | 19866-6c04f56db1b73ac6@postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19866
Logged by: Milo
Email address: 1548140642(at)qq(dot)com
PostgreSQL version: 18.6
Operating system: Linux/amd64
Description:
In a UTF-8 database, pg_catalog.acldefault(char, oid) produces MESSAGE_TEXT
containing a raw, invalid UTF-8 byte when the invalid object type is the
one-byte value 0x80. A client that decodes server responses as UTF-8 can
therefore fail to decode the diagnostic.
The diagnostic should remain valid in the server encoding. The byte should
be rendered in an encoding-safe form such as \200, as charout() and the
setweight() diagnostic do, rather than inserted as a raw standalone byte.
How to repeat:
Save the following as reproducer.sql and run `psql -X -d postgres -f
reproducer.sql` against a UTF-8 database.
CREATE TEMP TABLE encoding_result
(tested_function text,
message_is_invalid_utf8 boolean,
validation_sqlstate text);
DO $test$
DECLARE
captured_message text;
invalid_utf8 boolean;
validation_state text;
BEGIN
BEGIN
PERFORM pg_catalog.acldefault('\200'::pg_catalog."char", 10::oid);
RAISE EXCEPTION 'expected acldefault() to reject the invalid object
type';
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS captured_message = MESSAGE_TEXT;
END;
invalid_utf8 := false;
validation_state := NULL;
BEGIN
-- Converting away from the database encoding forces validation of the
-- UTF-8 source bytes; UTF8-to-UTF8 conversion would be optimized away.
PERFORM pg_catalog.convert_to(captured_message, 'LATIN1');
EXCEPTION WHEN OTHERS THEN
invalid_utf8 := true;
GET STACKED DIAGNOSTICS validation_state = RETURNED_SQLSTATE;
END;
INSERT INTO encoding_result
VALUES ('acldefault', invalid_utf8, validation_state);
BEGIN
PERFORM pg_catalog.setweight('a'::pg_catalog.tsvector,
'\200'::pg_catalog."char");
RAISE EXCEPTION 'expected setweight() to reject the invalid weight';
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS captured_message = MESSAGE_TEXT;
END;
invalid_utf8 := false;
validation_state := NULL;
BEGIN
PERFORM pg_catalog.convert_to(captured_message, 'LATIN1');
EXCEPTION WHEN OTHERS THEN
invalid_utf8 := true;
GET STACKED DIAGNOSTICS validation_state = RETURNED_SQLSTATE;
END;
INSERT INTO encoding_result
VALUES ('setweight_control', invalid_utf8, validation_state);
END
$test$;
SELECT tested_function, message_is_invalid_utf8, validation_sqlstate
FROM encoding_result
ORDER BY tested_function;
DROP TABLE encoding_result;
The recorded output was:
CREATE TABLE
DO
tested_function | message_is_invalid_utf8 | validation_sqlstate
-------------------+-------------------------+---------------------
acldefault | t | 22021
setweight_control | f |
(2 rows)
DROP TABLE
The acldefault() message therefore fails UTF-8 source validation with
SQLSTATE 22021, while the diagnostic produced by setweight() for the same
one-byte value remains valid.
The issue was reproduced on PostgreSQL 18.6 and PostgreSQL 20devel on
Linux/amd64.
This occurs when acldefault() is called with the high-bit one-byte "char"
value 0x80 as an invalid object type.
| From | Date | Subject | |
|---|---|---|---|
| Next Message | PG Bug reporting form | 2026-11-11 05:46:08 | BUG #19867: pg_verifybackup accepts out-of-range Timeline in backup manifest |
| Previous Message | PG Bug reporting form | 2026-11-11 05:36:09 | BUG #19865: WAL summary reader wraps block numbers for oversized chunk counts |