v3-0001-Make-EUC-KR-encoding-routines-self-contained.patch

application/octet-stream

Filename: v3-0001-Make-EUC-KR-encoding-routines-self-contained.patch
Type: application/octet-stream
Part: 0
Message: Re: Remove invalid SS2/SS3 handling from EUC-KR routines

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v3-0001
Subject: Make EUC-KR encoding routines self-contained
File+
doc/src/sgml/charset.sgml 1 1
src/common/wchar.c 32 4
From a79ecd2b1c8726837b11d8a0313d4b9ac5f123a1 Mon Sep 17 00:00:00 2001
From: SungJun Jang <sjjang112233@gmail.com>
Date: Thu, 14 May 2026 13:02:47 +0900
Subject: [PATCH v3] Make EUC-KR encoding routines self-contained

Per KS X 2901 (formerly KS C 5861-1992), EUC-KR designates only G0
(ASCII) and G1 (KS X 1001).  G2 and G3 are not designated, so SS2
(0x8E) and SS3 (0x8F) cannot appear as lead bytes and no 3-byte
sequence is ever valid in EUC-KR.

pg_euckr_verifychar() already reflects this: it has no SS2/SS3 case.
But pg_euckr_mblen(), pg_euckr_dsplen(), and pg_euckr2wchar_with_len()
delegated to the shared pg_euc_* helpers, which include SS2/SS3
handling for encodings that designate G2/G3.  Replace these with
EUC-KR-specific implementations, change pg_wchar_table[PG_EUC_KR]
maxmblen from 3 to 2, and update Table 23.3 from "1-3" to "1-2".

The only user-visible effect is that pg_encoding_max_length('EUC_KR')
now returns 2 instead of 3.

After this patch, EUC-KR's mb routines are structurally identical to
UHC's: IS_HIGHBIT_SET-only dispatch, 1-2 byte sequences, maxmblen=2.

No behavior change for valid EUC-KR data, since the verifier never
admits SS2 or SS3 as lead bytes.
---
 doc/src/sgml/charset.sgml |  2 +-
 src/common/wchar.c        | 36 ++++++++++++++++++++++++++++++++----
 2 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/doc/src/sgml/charset.sgml b/doc/src/sgml/charset.sgml
index 746e40bb9d2..5edaf51b56c 100644
--- a/doc/src/sgml/charset.sgml
+++ b/doc/src/sgml/charset.sgml
@@ -1862,7 +1862,7 @@ ORDER BY c COLLATE ebcdic;
          <entry>Korean</entry>
          <entry>Yes</entry>
          <entry>Yes</entry>
-         <entry>1&ndash;3</entry>
+         <entry>1&ndash;2</entry>
          <entry></entry>
         </row>
         <row>
diff --git a/src/common/wchar.c b/src/common/wchar.c
index 4c77e3e1dc8..3b8e1da862a 100644
--- a/src/common/wchar.c
+++ b/src/common/wchar.c
@@ -210,23 +210,51 @@ pg_eucjp_dsplen(const unsigned char *s)
 
 /*
  * EUC_KR
+ *
+ * Per KS X 2901 (formerly KS C 5861-1992), EUC-KR designates only G0
+ * (ASCII) and G1 (KS X 1001).  G2 and G3 are not designated, so the
+ * single-shift codes SS2 (0x8E) and SS3 (0x8F) never appear as lead
+ * bytes and no 3-byte sequence is ever valid.  These routines therefore
+ * implement EUC-KR directly rather than delegating to the shared
+ * pg_euc_* helpers, which include SS2/SS3 handling for encodings that
+ * designate G2/G3.
  */
 static int
 pg_euckr2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
 {
-	return pg_euc2wchar_with_len(from, to, len);
+	int			cnt = 0;
+
+	while (len > 0 && *from)
+	{
+		if (IS_HIGHBIT_SET(*from))	/* G1: KS X 1001, 2 bytes */
+		{
+			MB2CHAR_NEED_AT_LEAST(len, 2);
+			*to = *from++ << 8;
+			*to |= *from++;
+			len -= 2;
+		}
+		else					/* G0: ASCII */
+		{
+			*to = *from++;
+			len--;
+		}
+		to++;
+		cnt++;
+	}
+	*to = 0;
+	return cnt;
 }
 
 static int
 pg_euckr_mblen(const unsigned char *s)
 {
-	return pg_euc_mblen(s);
+	return IS_HIGHBIT_SET(*s) ? 2 : 1;
 }
 
 static int
 pg_euckr_dsplen(const unsigned char *s)
 {
-	return pg_euc_dsplen(s);
+	return IS_HIGHBIT_SET(*s) ? 2 : pg_ascii_dsplen(s);
 }
 
 /*
@@ -1865,7 +1893,7 @@ const pg_wchar_tbl pg_wchar_table[] = {
 	[PG_SQL_ASCII] = {pg_ascii2wchar_with_len, pg_wchar2single_with_len, pg_ascii_mblen, pg_ascii_dsplen, pg_ascii_verifychar, pg_ascii_verifystr, 1},
 	[PG_EUC_JP] = {pg_eucjp2wchar_with_len, pg_wchar2euc_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, pg_eucjp_verifychar, pg_eucjp_verifystr, 3},
 	[PG_EUC_CN] = {pg_euccn2wchar_with_len, pg_wchar2euc_with_len, pg_euccn_mblen, pg_euccn_dsplen, pg_euccn_verifychar, pg_euccn_verifystr, 3},
-	[PG_EUC_KR] = {pg_euckr2wchar_with_len, pg_wchar2euc_with_len, pg_euckr_mblen, pg_euckr_dsplen, pg_euckr_verifychar, pg_euckr_verifystr, 3},
+	[PG_EUC_KR] = {pg_euckr2wchar_with_len, pg_wchar2euc_with_len, pg_euckr_mblen, pg_euckr_dsplen, pg_euckr_verifychar, pg_euckr_verifystr, 2},
 	[PG_EUC_TW] = {pg_euctw2wchar_with_len, pg_wchar2euc_with_len, pg_euctw_mblen, pg_euctw_dsplen, pg_euctw_verifychar, pg_euctw_verifystr, 4},
 	[PG_EUC_JIS_2004] = {pg_eucjp2wchar_with_len, pg_wchar2euc_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, pg_eucjp_verifychar, pg_eucjp_verifystr, 3},
 	[PG_UTF8] = {pg_utf2wchar_with_len, pg_wchar2utf_with_len, pg_utf_mblen, pg_utf_dsplen, pg_utf8_verifychar, pg_utf8_verifystr, 4},
-- 
2.48.1.windows.1