fix(redshift): skip WKB probe slice on multibyte text values

Redshift reads run every simple-query cell through decode_pg_text_wkb
with an unknown column type. The probe sliced hex[..2] before the
is_ascii() guard, so any cell starting with a 3-4 byte UTF-8 character
with an even byte length >= 10 panicked on a non-char boundary and
aborted the process under panic = abort (Windows BEX64 in dbx.exe).
Check is_ascii() first so ordinary multibyte text passes through.

Closes #7958
This commit is contained in:
t8y2
2026-09-05 16:10:38 +08:00
parent cbaccb3a3a
commit 641f82c962
+16 -1
View File
@@ -972,7 +972,11 @@ fn decode_pg_text_wkb(value: &str) -> Option<super::wkb::DecodedGeometry> {
.or_else(|| trimmed.strip_prefix("\\x"))
.or_else(|| trimmed.strip_prefix("\\X"))
.unwrap_or(trimmed);
if hex.len() < 10 || !hex.len().is_multiple_of(2) || !matches!(&hex[..2], "00" | "01") || !hex.is_ascii() {
// `is_ascii()` must be checked before slicing `hex[..2]`: multibyte UTF-8
// text (e.g. Redshift simple-query values probed with an unknown column
// type) would otherwise panic on a non-char byte boundary and abort the
// process under `panic = "abort"`.
if hex.len() < 10 || !hex.len().is_multiple_of(2) || !hex.is_ascii() || !matches!(&hex[..2], "00" | "01") {
return None;
}
let bytes = hex
@@ -9470,6 +9474,17 @@ mod tests {
assert_eq!(pg_text_fallback_value("SRID=4326;point(1 2)", None), (serde_json::json!("point(1 2)"), Some(4326)));
}
#[test]
fn postgres_text_fallback_does_not_panic_on_multibyte_text() {
// Redshift reads decode every simple-query value through the hex-WKB
// probe with an unknown column type, so ordinary multibyte text must
// pass through instead of slicing at a non-char byte boundary.
for value in ["中文字符测试数据", "🚚运输状态标签", "0101中文不是几何数据"] {
assert_eq!(pg_text_fallback_value(value, None), (serde_json::json!(value), None));
assert_eq!(pg_text_fallback_value(value, Some(PgColType::Geometry)), (serde_json::json!(value), None));
}
}
struct DockerPostgres {
name: String,
port: u16,