Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1x8spC-00000001a3c-3lYE for pgsql-hackers@arkaria.postgresql.org; Tue, 22 Sep 2026 05:13:51 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.98.2) (envelope-from ) id 1x8spB-0000000DbdH-0Q4Z for pgsql-hackers@arkaria.postgresql.org; Tue, 22 Sep 2026 05:13:49 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1x8spA-0000000Dbd5-06lJ for pgsql-hackers@lists.postgresql.org; Tue, 22 Sep 2026 05:13:48 +0000 Received: from fhigh-a1-smtp.messagingengine.com ([103.168.172.152]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1x8sp7-00000000c4g-2232 for pgsql-hackers@lists.postgresql.org; Tue, 22 Sep 2026 05:13:47 +0000 Received: from phl-compute-05.internal (phl-compute-05.internal [10.202.2.45]) by mailfhigh.phl.internal (Postfix) with ESMTP id 8D94C1400173; Tue, 22 Sep 2026 01:13:44 -0400 (EDT) Received: from phl-imap-15 ([10.202.2.104]) by phl-compute-05.internal (MEProxy); Tue, 22 Sep 2026 01:13:44 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=partin.io; h=cc :cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to; s=fm1; t=1790054024; x=1790140424; bh=cwdfNYpPeFfkarEY4Z9Fzrfx3J/YXvITANCYpD/xD7c=; b= mF1j8Ljb6Iqt23ufXJ3H/5HNACXt1gHGXJUUzYYQucvq9EqjioLHKm2dkNmVY1fu LicJAIvYkIICfM4uGeb403ZMk2Um9d86OLRnXjUIQZ88SEFwuUFmLBVhyHI4Av9j gbSmXIcQqSawgWpExD6cEtJkAIxZ/FMhPUeIDZXgzSN/TcXagyoB9imsN7qxcBbI ziOeoFOoeRcNHPurEt4kDxCaAGshvQaqg2l5LWC3uBBU4zb6S7Z+tDz+daKszFu9 vrC51AbEErgFiXh27gsN3Rb6kuy/WaFPVkfBTB0goKl/DdTs2tQl59ae/frQt1iI pH+oRI60BjAwzGitIrgTfg== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:subject:subject:to:to:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1790054024; x= 1790140424; bh=cwdfNYpPeFfkarEY4Z9Fzrfx3J/YXvITANCYpD/xD7c=; b=k j3vgtHZmyCDZeP2IY3NKmuZxTkz+da3fyvzK6cI1PJBfJPMOrr9KJOhroywkyHle G5C2/8v7EjODuFYeHZj8LzgRBo2pD23bKjHdkdBxduFvbzMOptalogAtzfwkUNxL EpR6ZvB+OueqMKjyuvc+TM3KUrUhnChfFkAdTHatCutozc1HwGxNVKNw9ygptac/ 3Pvnp6eOLtukT3TdN011z11vFh0HAtPwfdNWbm9aH16pOic651A4hCGr4pMDuqUm bMkoPWLqJjH/rYbkIsdiUzZ5m6FD80TBrZnXERnJdM+O8ne+fTEFkHCLbM07EYBW Yx3jQWjIftfVzXf2Xh6wQ== X-ME-Sender: X-ME-Proxy-Cause: dmFkZTF+CPMYIY6sxgfHg1uV8g2xTgswaXkythpm7Ncg1oOAwqr7BYl1fH1U64vvNrWr7E NXIl0IKtyiORQmc1lh3qo3HGKRMxQy3gOETMQttQ653BFKT+d1wCUdOAdx+MXr99MOUnC4 mJEvsXwLrSR6BSTjxchOGirKDM6zoX+tL/9tnMQu3mbJLmB0saQprhm+XZ8k0HiauiXQhq /HFPmizIVQjNjobu+9sBi/JvUMlX9u2r3UTCkz+qLuYQYKYpgP9DhMTjCdax5ts5+9vmeH bmmMYKjfCZSZGIyF1rH2yGvuBVc9rlazA8m7KWxmJf/Yx1igeHCQ3O30lQ/cQ8PBVfhMnY 6trp6Kdh2rF0Imy3SRGDNVT+EllSmGd7yM2/4xY8ShCG6MCH9rCGwMmVtOcJ1RSjs/tKfv agXBKKJRKlqk/YMbHi3ky3iFxNBUPyp/J5kq6cHpSHtSJ84IZE8cpqQ1ox+SzTyhnQ3H5a Rn69I3aFmOxlhKmeIk7OELkq1z9kqiTJR/UdGmF//o9DmFpXJ1xF8IuiNITNJnZOtJ4D5u Yb2SMwAYLxyIIbGwHXa/okA+ySd6e6ZyOhkptudf8v/bNXSk+7rgnmYrcxCSv0z2yk32UK 3z305+68mFUzutyIPatvt9DwxKn2ay9IpHb0XGD0fQo8iTBzBPDyuqG/9b1w X-ME-Proxy: Feedback-ID: idd01497b:Fastmail Received: by mailuser.phl.internal (Postfix, from userid 501) id 1774E780070; Tue, 22 Sep 2026 01:13:44 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface Mime-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=UTF-8 Date: Tue, 22 Sep 2026 05:13:43 +0000 Message-Id: Cc: "pgsql-hackers" Subject: Re: Stop asserting that Unicode normalization consumes its whole input To: "John Naylor" From: "Tristan Partin" X-Mailer: aerc 0.22.0-23-g35fceeedf4d2-dirty References: In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Mon Sep 21, 2026 at 11:46 PM CDT, John Naylor wrote: > On Sat, Sep 19, 2026 at 12:00=E2=80=AFAM Tristan Partin wrote: >> >> normalize() and IS NORMALIZED determine how many code points their input >> holds with pg_mbstrlen_with_len(). They then decode exactly that many >> code points, and assert afterward that this consumed the entire datum. >> That invariant does not hold because pg_mbstrlen_with_len() stops at the >> first of "limit" or a NUL. > > The limit here is VARSIZE_ANY_EXHDR(input) , which is the entire > length. This patch seems like it's weakening an assertion for a case > that shouldn't happen. (I haven't looked at the tests in encoding.sql > that force non-standard behavior, so I'm not sure what the context was > there...) Hey John, In regress.c, we have the following function: /* Convert bytea to text without validation for corruption tests from SQL.= */ PG_FUNCTION_INFO_V1(test_bytea_to_text); Datum test_bytea_to_text(PG_FUNCTION_ARGS) { PG_RETURN_TEXT_P(PG_GETARG_BYTEA_PP(0)); } In encoding.sql, we do things like the following: CREATE TABLE regress_encoding(good text, truncated text, with_nul text, tr= uncated_with_nul text); INSERT INTO regress_encoding VALUES ('caf=C3=A9', 'caf' || test_bytea_to_text('\xc3'), 'caf=C3=A9' || test_bytea_to_text('\x00') || 'dcba', 'caf' || test_bytea_to_text('\xc300') || 'dcba'); ... -- NUL =3D terminator SELECT length(with_nul) FROM regress_encoding; SELECT substring(with_nul, 3, 1) FROM regress_encoding; SELECT substring(with_nul, 4, 1) FROM regress_encoding; SELECT substring(with_nul, 5, 1) FROM regress_encoding; SELECT convert_to(substring(with_nul, 5, 1), 'UTF8') FROM regress_encoding= ; SELECT regexp_replace(with_nul, '^caf(.)$', '\1') FROM regress_encoding; -- NUL =3D character SELECT with_nul, reverse(with_nul), reverse(reverse(with_nul)) FROM regres= s_encoding; Output file: SELECT length(with_nul) FROM regress_encoding; length -------- 4 (1 row) =09 SELECT substring(with_nul, 3, 1) FROM regress_encoding; substring ----------- f (1 row) =09 SELECT substring(with_nul, 4, 1) FROM regress_encoding; substring ----------- =C3=A9 (1 row) =09 SELECT substring(with_nul, 5, 1) FROM regress_encoding; substring ----------- =09 (1 row) =09 SELECT convert_to(substring(with_nul, 5, 1), 'UTF8') FROM regress_encoding= ; convert_to ------------ \x (1 row) =09 SELECT regexp_replace(with_nul, '^caf(.)$', '\1') FROM regress_encoding; regexp_replace ---------------- =C3=A9 (1 row) =09 -- NUL =3D character SELECT with_nul, reverse(with_nul), reverse(reverse(with_nul)) FROM regres= s_encoding; with_nul | reverse | reverse ----------+---------+--------- caf=C3=A9 | abcd | caf=C3=A9 (1 row) You can see that we are doing some shenanigans to test how text values work in various string functions for corrupted values. We don't do the same tests for normalize() and IS NORMALIZED, which is why I made the change to <=3D instead of =3D=3D. Otherwise, builds with casserts enabled w= ill crash, which doesn't seem like what we intend to do given the array of tests we do to make sure things still work. I would say that you're right that this patch does weaken an assertion, but it is something that Postgres tests for just to make sure things continue to work. --=20 Tristan Partin PostgreSQL Contributors Team AWS (https://aws.amazon.com)