From 362ca98bbdfef14f7f85f53e6d12fdcd8120ea22 Mon Sep 17 00:00:00 2001 From: Ygor Souza Date: Fri, 12 Jul 2024 21:54:37 +0200 Subject: [PATCH] fix(postgres): don't panic if `M` or `C` Notice fields are not UTF-8 This has been observed with an old version of PostgreSQL (11.0.4) running on Windows Server 2016 with windows-1252 encoding and French locale. This change replaces invalid UTF-8 fields with a default string, so the other fields can still be read if they are valid. --- sqlx-postgres/src/message/response.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/sqlx-postgres/src/message/response.rs b/sqlx-postgres/src/message/response.rs index bb79ddd4..9ee4ea09 100644 --- a/sqlx-postgres/src/message/response.rs +++ b/sqlx-postgres/src/message/response.rs @@ -6,6 +6,11 @@ use sqlx_core::bytes::Bytes; use crate::error::Error; use crate::io::Decode; +const INVALID_UTF8: &str = "Postgres returned a non-UTF-8 string for its error message. \ + This is most likely due to an error that occurred during authentication and \ + the default lc_messages locale is not binary-compatible with UTF-8. \ + See the server logs for the error details."; + #[derive(Debug, Copy, Clone, Eq, PartialEq)] #[repr(u8)] pub enum PgSeverity { @@ -100,8 +105,7 @@ impl Notice { #[inline] fn get_cached_str(&self, cache: (u16, u16)) -> &str { - // unwrap: this cannot fail at this stage - from_utf8(&self.storage[cache.0 as usize..cache.1 as usize]).unwrap() + from_utf8(&self.storage[cache.0 as usize..cache.1 as usize]).unwrap_or(INVALID_UTF8) } } @@ -203,13 +207,7 @@ impl<'a> Iterator for Fields<'a> { fn notice_protocol_err() -> Error { // https://github.com/launchbadge/sqlx/issues/1144 - Error::Protocol( - "Postgres returned a non-UTF-8 string for its error message. \ - This is most likely due to an error that occurred during authentication and \ - the default lc_messages locale is not binary-compatible with UTF-8. \ - See the server logs for the error details." - .into(), - ) + Error::Protocol(INVALID_UTF8.into()) } #[test]