From b3bbdab7055e6e8ea75586f8c3c6b81d7fcadff4 Mon Sep 17 00:00:00 2001 From: Valentin Date: Thu, 7 Jul 2022 03:23:29 +0200 Subject: [PATCH] Fix panic in Postgres Bytes decode (#1948) This function can panic due to slicing out of bounds when the server responds without the `\x` prefix. With this commit we instead error and also ensure that the prefix is what we expect instead of blindly removing it. Not directly related to the panic, we replace as_str() with as_bytes() because there is no reason to perform a utf8 validity check when hex::decode already checks that the content is valid. --- sqlx-core/src/postgres/types/bytes.rs | 6 +++++- tests/postgres/postgres.rs | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/sqlx-core/src/postgres/types/bytes.rs b/sqlx-core/src/postgres/types/bytes.rs index 2a3433e5..aadc2ef3 100644 --- a/sqlx-core/src/postgres/types/bytes.rs +++ b/sqlx-core/src/postgres/types/bytes.rs @@ -55,7 +55,11 @@ impl Decode<'_, Postgres> for Vec { PgValueFormat::Binary => value.as_bytes()?.to_owned(), PgValueFormat::Text => { // BYTEA is formatted as \x followed by hex characters - hex::decode(&value.as_str()?[2..])? + let text = value + .as_bytes()? + .strip_prefix(b"\\x") + .ok_or("text does not start with \\x")?; + hex::decode(text)? } }) } diff --git a/tests/postgres/postgres.rs b/tests/postgres/postgres.rs index 2f6d0e0f..30f06b59 100644 --- a/tests/postgres/postgres.rs +++ b/tests/postgres/postgres.rs @@ -1713,3 +1713,16 @@ async fn test_advisory_locks() -> anyhow::Result<()> { Ok(()) } + +#[sqlx_macros::test] +async fn test_postgres_bytea_hex_deserialization_errors() -> anyhow::Result<()> { + let mut conn = new::().await?; + conn.execute("SET bytea_output = 'escape';").await?; + for value in ["", "DEADBEEF"] { + let query = format!("SELECT '\\x{}'::bytea", value); + let res: sqlx::Result> = conn.fetch_one(query.as_str()).await?.try_get(0usize); + // Deserialization only supports hex format so this should error and definitely not panic. + res.unwrap_err(); + } + Ok(()) +}