Skip to content

Commit

Permalink
Handle non-UTF8 error fields
Browse files Browse the repository at this point in the history
  • Loading branch information
sfackler committed Jul 6, 2024
1 parent c2b5c8a commit 263b006
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 20 deletions.
10 changes: 8 additions & 2 deletions postgres-protocol/src/message/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ impl<'a> FallibleIterator for ErrorFields<'a> {
}

let value_end = find_null(self.buf, 0)?;
let value = get_str(&self.buf[..value_end])?;
let value = &self.buf[..value_end];
self.buf = &self.buf[value_end + 1..];

Ok(Some(ErrorField { type_, value }))
Expand All @@ -642,7 +642,7 @@ impl<'a> FallibleIterator for ErrorFields<'a> {

pub struct ErrorField<'a> {
type_: u8,
value: &'a str,
value: &'a [u8],
}

impl<'a> ErrorField<'a> {
Expand All @@ -652,7 +652,13 @@ impl<'a> ErrorField<'a> {
}

#[inline]
#[deprecated(note = "use value_bytes instead", since = "0.6.7")]
pub fn value(&self) -> &str {
str::from_utf8(self.value).expect("error field value contained non-UTF8 bytes")
}

#[inline]
pub fn value_bytes(&self) -> &[u8] {
self.value
}
}
Expand Down
37 changes: 19 additions & 18 deletions tokio-postgres/src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,47 +107,48 @@ impl DbError {
let mut routine = None;

while let Some(field) = fields.next()? {
let value = String::from_utf8_lossy(field.value_bytes());
match field.type_() {
b'S' => severity = Some(field.value().to_owned()),
b'C' => code = Some(SqlState::from_code(field.value())),
b'M' => message = Some(field.value().to_owned()),
b'D' => detail = Some(field.value().to_owned()),
b'H' => hint = Some(field.value().to_owned()),
b'S' => severity = Some(value.into_owned()),
b'C' => code = Some(SqlState::from_code(&value)),
b'M' => message = Some(value.into_owned()),
b'D' => detail = Some(value.into_owned()),
b'H' => hint = Some(value.into_owned()),
b'P' => {
normal_position = Some(field.value().parse::<u32>().map_err(|_| {
normal_position = Some(value.parse::<u32>().map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidInput,
"`P` field did not contain an integer",
)
})?);
}
b'p' => {
internal_position = Some(field.value().parse::<u32>().map_err(|_| {
internal_position = Some(value.parse::<u32>().map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidInput,
"`p` field did not contain an integer",
)
})?);
}
b'q' => internal_query = Some(field.value().to_owned()),
b'W' => where_ = Some(field.value().to_owned()),
b's' => schema = Some(field.value().to_owned()),
b't' => table = Some(field.value().to_owned()),
b'c' => column = Some(field.value().to_owned()),
b'd' => datatype = Some(field.value().to_owned()),
b'n' => constraint = Some(field.value().to_owned()),
b'F' => file = Some(field.value().to_owned()),
b'q' => internal_query = Some(value.into_owned()),
b'W' => where_ = Some(value.into_owned()),
b's' => schema = Some(value.into_owned()),
b't' => table = Some(value.into_owned()),
b'c' => column = Some(value.into_owned()),
b'd' => datatype = Some(value.into_owned()),
b'n' => constraint = Some(value.into_owned()),
b'F' => file = Some(value.into_owned()),
b'L' => {
line = Some(field.value().parse::<u32>().map_err(|_| {
line = Some(value.parse::<u32>().map_err(|_| {
io::Error::new(
io::ErrorKind::InvalidInput,
"`L` field did not contain an integer",
)
})?);
}
b'R' => routine = Some(field.value().to_owned()),
b'R' => routine = Some(value.into_owned()),
b'V' => {
parsed_severity = Some(Severity::from_str(field.value()).ok_or_else(|| {
parsed_severity = Some(Severity::from_str(&value).ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
"`V` field contained an invalid value",
Expand Down

0 comments on commit 263b006

Please sign in to comment.