1use bytes::{Buf, Bytes, BytesMut};
7use small_collections::SmallString;
8
9use crate::{
10 error::{DbError, Error},
11 oid::Oid,
12};
13
14#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct FieldDescription {
17 pub name: String,
19 pub table_oid: u32,
21 pub column_attr: i16,
23 pub type_oid: Oid,
25 pub type_size: i16,
27 pub type_mod: i32,
29 pub format: i16,
31}
32
33impl FieldDescription {
34 pub fn is_table_column(&self) -> bool {
36 self.table_oid != 0 && self.column_attr > 0
37 }
38}
39
40#[derive(Debug)]
42pub enum BackendMessage {
43 AuthenticationOk,
45 AuthenticationCleartextPassword,
47 AuthenticationMd5Password([u8; 4]),
49 AuthenticationSasl(Vec<String>),
51 AuthenticationSaslContinue(Bytes),
53 AuthenticationSaslFinal(Bytes),
55 BackendKeyData {
57 pid: i32,
59 secret_key: i32,
61 },
62 ParameterStatus {
64 name: String,
66 value: String,
68 },
69 ReadyForQuery(u8),
71 RowDescription(Vec<FieldDescription>),
73 ParameterDescription(Vec<Oid>),
75 DataRow(Bytes),
77 CommandComplete(Bytes),
79 ParseComplete,
81 BindComplete,
83 CloseComplete,
85 NoData,
87 PortalSuspended,
89 EmptyQueryResponse,
91 ErrorResponse(DbError),
93 NoticeResponse(DbError),
95 NotificationResponse {
97 pid: i32,
99 channel: String,
101 payload: String,
103 },
104 CopyInResponse {
106 format: u8,
108 column_formats: Vec<i16>,
110 },
111 CopyOutResponse {
113 format: u8,
115 column_formats: Vec<i16>,
117 },
118 CopyData(Bytes),
120 CopyDone,
122 NegotiateProtocolVersion {
124 newest_minor: i32,
126 unsupported: Vec<String>,
128 },
129}
130
131pub const DEFAULT_MAX_MESSAGE_LEN: usize = 128 * 1024 * 1024;
143
144pub fn decode(buf: &mut BytesMut) -> Result<Option<BackendMessage>, Error> {
154 decode_with_limit(buf, DEFAULT_MAX_MESSAGE_LEN)
155}
156
157pub fn decode_with_limit(buf: &mut BytesMut, max: usize) -> Result<Option<BackendMessage>, Error> {
168 let max = max.min(i32::MAX as usize);
169 if buf.len() < 5 {
170 return Ok(None);
171 }
172 let tag = buf[0];
173 let len = i32::from_be_bytes([buf[1], buf[2], buf[3], buf[4]]);
174 if len < 4 {
175 return Err(Error::Decode(format!("invalid message length {len}")));
176 }
177 let len = usize::try_from(len).map_err(|_| Error::Decode(format!("invalid message length {len}")))?;
179 if len > max {
180 return Err(Error::Decode(format!("message length {len} exceeds the {max} byte limit")));
181 }
182 let total = 1 + len;
183 if buf.len() < total {
184 return Ok(None);
185 }
186
187 let frame = buf.split_to(total).freeze();
188 let payload = frame.slice(5..);
189 parse(tag, payload).map(Some)
190}
191
192fn parse(tag: u8, payload: Bytes) -> Result<BackendMessage, Error> {
193 match tag {
194 b'R' => {
195 let mut r = Reader::new(payload);
196 let kind = r.i32()?;
197 match kind {
198 0 => Ok(BackendMessage::AuthenticationOk),
199 3 => Ok(BackendMessage::AuthenticationCleartextPassword),
200 5 => {
201 let salt = r.bytes(4)?;
202 Ok(BackendMessage::AuthenticationMd5Password([salt[0], salt[1], salt[2], salt[3]]))
203 }
204 10 => {
205 let mut mechanisms = Vec::with_capacity(r.cap(2, 2));
207 while r.remaining() > 0 {
208 let m = r.cstr()?;
209 if m.is_empty() {
210 break;
211 }
212 mechanisms.push(String::from_utf8_lossy(&m).into_owned());
213 }
214 Ok(BackendMessage::AuthenticationSasl(mechanisms))
215 }
216 11 => Ok(BackendMessage::AuthenticationSaslContinue(r.rest())),
217 12 => Ok(BackendMessage::AuthenticationSaslFinal(r.rest())),
218 other => Err(Error::Auth(format!("unsupported authentication method {other}"))),
219 }
220 }
221 b'K' => {
222 let mut r = Reader::new(payload);
223 Ok(BackendMessage::BackendKeyData {
224 pid: r.i32()?,
225 secret_key: r.i32()?,
226 })
227 }
228 b'S' => {
229 let mut r = Reader::new(payload);
230 Ok(BackendMessage::ParameterStatus {
231 name: r.string()?,
232 value: r.string()?,
233 })
234 }
235 b'Z' => {
236 let mut r = Reader::new(payload);
237 Ok(BackendMessage::ReadyForQuery(r.u8()?))
238 }
239 b'T' => {
240 let mut r = Reader::new(payload);
241 let count = r.count16()?;
242 let mut fields = Vec::with_capacity(r.cap(count, 19));
244 for _ in 0..count {
245 fields.push(FieldDescription {
246 name: r.string()?,
247 table_oid: r.u32()?,
248 column_attr: r.i16()?,
249 type_oid: r.u32()?,
250 type_size: r.i16()?,
251 type_mod: r.i32()?,
252 format: r.i16()?,
253 });
254 }
255 Ok(BackendMessage::RowDescription(fields))
256 }
257 b't' => {
258 let mut r = Reader::new(payload);
259 let count = r.count16()?;
260 let mut oids = Vec::with_capacity(r.cap(count, 4));
261 for _ in 0..count {
262 oids.push(r.u32()?);
263 }
264 Ok(BackendMessage::ParameterDescription(oids))
265 }
266 b'D' => Ok(BackendMessage::DataRow(payload)),
267 b'C' => {
268 let mut r = Reader::new(payload);
269 Ok(BackendMessage::CommandComplete(r.cstr()?))
270 }
271 b'1' => Ok(BackendMessage::ParseComplete),
272 b'2' => Ok(BackendMessage::BindComplete),
273 b'3' => Ok(BackendMessage::CloseComplete),
274 b'n' => Ok(BackendMessage::NoData),
275 b's' => Ok(BackendMessage::PortalSuspended),
276 b'I' => Ok(BackendMessage::EmptyQueryResponse),
277 b'E' => {
278 let err = decode_error(payload)?;
279 Err(Error::Server(Box::new(err)))
280 }
281 b'N' => {
282 let err = decode_error(payload)?;
283 Ok(BackendMessage::NoticeResponse(err))
284 }
285 b'A' => {
286 let mut r = Reader::new(payload);
287 Ok(BackendMessage::NotificationResponse {
288 pid: r.i32()?,
289 channel: r.string()?,
290 payload: r.string()?,
291 })
292 }
293 b'G' => {
294 let mut r = Reader::new(payload);
295 let format = r.u8()?;
296 let count = r.count16()?;
297 let mut column_formats = Vec::with_capacity(r.cap(count, 2));
298 for _ in 0..count {
299 column_formats.push(r.i16()?);
300 }
301 Ok(BackendMessage::CopyInResponse {
302 format,
303 column_formats,
304 })
305 }
306 b'W' => Err(Error::Protocol(
307 "CopyBothResponse (streaming replication) is not supported".into(),
308 )),
309 b'H' => {
310 let mut r = Reader::new(payload);
311 let format = r.u8()?;
312 let count = r.count16()?;
313 let mut column_formats = Vec::with_capacity(r.cap(count, 2));
314 for _ in 0..count {
315 column_formats.push(r.i16()?);
316 }
317 Ok(BackendMessage::CopyOutResponse {
318 format,
319 column_formats,
320 })
321 }
322 b'd' => Ok(BackendMessage::CopyData(payload)),
323 b'c' => Ok(BackendMessage::CopyDone),
324 b'v' => {
325 let mut r = Reader::new(payload);
326 let newest_minor = r.i32()?;
327 let count = r.count32()?;
328 let mut unsupported = Vec::with_capacity(r.cap(count, 1));
329 for _ in 0..count {
330 unsupported.push(r.string()?);
331 }
332 Ok(BackendMessage::NegotiateProtocolVersion {
333 newest_minor,
334 unsupported,
335 })
336 }
337 other => Err(Error::Protocol(format!("unknown message tag {:?}", other as char))),
338 }
339}
340
341fn decode_error(payload: Bytes) -> Result<DbError, Error> {
342 let mut r = Reader::new(payload);
343 let mut err = DbError::default();
344 while r.remaining() > 0 {
345 let field = r.u8()?;
346 if field == 0 {
347 break;
348 }
349 match field {
350 b'S' | b'V' => err.severity = r.small_string_lossy::<8>()?,
352 b'C' => err.code = r.small_string_lossy::<5>()?,
353 b'M' => err.message = r.string_lossy()?,
354 b'D' => err.detail = Some(r.string_lossy()?),
355 b'H' => err.hint = Some(r.string_lossy()?),
356 b'P' => err.position = r.string_lossy()?.parse().ok(),
357 b'n' => err.constraint = Some(r.string_lossy()?),
358 b't' => err.table = Some(r.string_lossy()?),
359 b'c' => err.column = Some(r.string_lossy()?),
360 b's' => err.schema = Some(r.string_lossy()?),
361 b'd' => err.data_type = Some(r.string_lossy()?),
362 _ => {
364 let _ = r.string_lossy()?;
365 }
366 }
367 }
368 Ok(err)
369}
370
371struct Reader {
373 buf: Bytes,
374}
375
376impl Reader {
377 fn new(buf: Bytes) -> Self {
378 Reader {
379 buf,
380 }
381 }
382
383 fn remaining(&self) -> usize {
384 self.buf.len()
385 }
386
387 fn rest(self) -> Bytes {
388 self.buf
389 }
390
391 fn u8(&mut self) -> Result<u8, Error> {
392 if self.buf.len() < 1 {
393 return Err(Error::Decode("unexpected end of message".into()));
394 }
395 Ok(self.buf.get_u8())
396 }
397
398 fn i16(&mut self) -> Result<i16, Error> {
399 if self.buf.len() < 2 {
400 return Err(Error::Decode("unexpected end of message".into()));
401 }
402 Ok(self.buf.get_i16())
403 }
404
405 fn i32(&mut self) -> Result<i32, Error> {
406 if self.buf.len() < 4 {
407 return Err(Error::Decode("unexpected end of message".into()));
408 }
409 Ok(self.buf.get_i32())
410 }
411
412 fn u32(&mut self) -> Result<u32, Error> {
413 Ok(self.i32()?.cast_unsigned())
414 }
415
416 fn count16(&mut self) -> Result<usize, Error> {
419 let n = self.i16()?;
420 usize::try_from(n).map_err(|_| Error::Decode(format!("invalid element count {n}")))
421 }
422
423 fn count32(&mut self) -> Result<usize, Error> {
426 let n = self.i32()?;
427 usize::try_from(n).map_err(|_| Error::Decode(format!("invalid element count {n}")))
428 }
429
430 fn cap(&self, count: usize, min_bytes_per_item: usize) -> usize {
434 count.min(self.buf.len() / min_bytes_per_item.max(1))
435 }
436
437 fn bytes(&mut self, n: usize) -> Result<Bytes, Error> {
438 if self.buf.len() < n {
439 return Err(Error::Decode("unexpected end of message".into()));
440 }
441 Ok(self.buf.split_to(n))
442 }
443
444 fn cstr(&mut self) -> Result<Bytes, Error> {
445 match self.buf.iter().position(|&b| b == 0) {
446 Some(pos) => {
447 let s = self.buf.split_to(pos);
448 self.buf.advance(1);
449 Ok(s)
450 }
451 None => Err(Error::Decode("unterminated string".into())),
452 }
453 }
454
455 fn string(&mut self) -> Result<String, Error> {
456 let bytes = self.cstr()?;
457 String::from_utf8(bytes.to_vec()).map_err(|e| Error::Decode(format!("invalid UTF-8: {e}")))
458 }
459
460 fn string_lossy(&mut self) -> Result<String, Error> {
466 let bytes = self.cstr()?;
467 Ok(String::from_utf8_lossy(&bytes).into_owned())
468 }
469
470 fn small_string_lossy<const N: usize>(&mut self) -> Result<SmallString<N>, Error> {
476 let bytes = self.cstr()?;
477 Ok(SmallString::from_utf8_lossy(&bytes))
478 }
479}
480
481#[cfg(test)]
482mod tests {
483 use super::*;
484
485 fn message(tag: u8, payload: &[u8]) -> BytesMut {
486 let mut buf = BytesMut::new();
487 buf.extend_from_slice(&[tag]);
488 buf.extend_from_slice(&i32::try_from(payload.len() + 4).unwrap().to_be_bytes());
489 buf.extend_from_slice(payload);
490 buf
491 }
492
493 #[test]
494 fn incomplete_returns_none() {
495 let mut buf = BytesMut::from(&b"R"[..]);
496 assert!(decode(&mut buf).unwrap().is_none());
497 }
498
499 #[test]
500 fn decode_ready_for_query() {
501 let mut buf = message(b'Z', &[b'I']);
502 match decode(&mut buf).unwrap().unwrap() {
503 BackendMessage::ReadyForQuery(s) => assert_eq!(s, b'I'),
504 other => panic!("unexpected {other:?}"),
505 }
506 }
507
508 #[test]
509 fn decode_error_response() {
510 let mut payload = Vec::new();
512 payload.extend_from_slice(b"SERROR\0");
513 payload.extend_from_slice(b"C23505\0");
514 payload.extend_from_slice(b"Mduplicate key\0");
515 payload.extend_from_slice(b"nusers_pkey\0");
516 payload.push(0);
517 let mut buf = message(b'E', &payload);
518 match decode(&mut buf).unwrap_err() {
519 Error::Server(err) => {
520 assert_eq!(err.code, "23505");
521 assert!(err.is_unique_violation());
522 assert_eq!(err.constraint.as_deref(), Some("users_pkey"));
523 }
524 other => panic!("unexpected {other:?}"),
525 }
526 }
527
528 #[test]
529 fn decode_row_description() {
530 let mut payload = Vec::new();
531 payload.extend_from_slice(&1i16.to_be_bytes());
532 payload.extend_from_slice(b"id\0");
533 payload.extend_from_slice(&0u32.to_be_bytes());
534 payload.extend_from_slice(&0i16.to_be_bytes());
535 payload.extend_from_slice(&23u32.to_be_bytes());
536 payload.extend_from_slice(&4i16.to_be_bytes());
537 payload.extend_from_slice(&(-1i32).to_be_bytes());
538 payload.extend_from_slice(&1i16.to_be_bytes());
539 let mut buf = message(b'T', &payload);
540 match decode(&mut buf).unwrap().unwrap() {
541 BackendMessage::RowDescription(fields) => {
542 assert_eq!(fields.len(), 1);
543 assert_eq!(fields[0].name, "id");
544 assert_eq!(fields[0].type_oid, 23);
545 }
546 other => panic!("unexpected {other:?}"),
547 }
548 }
549
550 #[test]
551 fn decode_parameter_description() {
552 let mut payload = Vec::new();
553 payload.extend_from_slice(&2i16.to_be_bytes());
554 payload.extend_from_slice(&23u32.to_be_bytes());
555 payload.extend_from_slice(&25u32.to_be_bytes());
556 let mut buf = message(b't', &payload);
557 match decode(&mut buf).unwrap().unwrap() {
558 BackendMessage::ParameterDescription(oids) => assert_eq!(oids, vec![23, 25]),
559 other => panic!("unexpected {other:?}"),
560 }
561 }
562
563 #[test]
564 fn negative_counts_are_rejected_not_panicking() {
565 for tag in [b'T', b't'] {
566 let mut p = Vec::new();
567 p.extend_from_slice(&(-1i16).to_be_bytes());
568 let mut buf = message(tag, &p);
569 let err = decode(&mut buf).unwrap_err();
570 assert!(matches!(err, Error::Decode(_)), "tag {}: {err:?}", tag as char);
571 }
572
573 let mut p = Vec::new();
575 p.push(1u8);
576 p.extend_from_slice(&(-3i16).to_be_bytes());
577 for tag in [b'G', b'W', b'H'] {
578 let mut buf = message(tag, &p);
579 assert!(decode(&mut buf).is_err());
580 }
581
582 let mut p = Vec::new();
584 p.extend_from_slice(&3i32.to_be_bytes());
585 p.extend_from_slice(&(-1i32).to_be_bytes());
586 let mut buf = message(b'v', &p);
587 assert!(decode(&mut buf).is_err());
588 }
589
590 #[test]
591 fn huge_counts_do_not_allocate_the_payload_size() {
592 let mut p = Vec::new();
595 p.extend_from_slice(&32767i16.to_be_bytes());
596 let mut buf = message(b'T', &p);
597 assert!(decode(&mut buf).is_err());
598
599 let mut p = Vec::new();
600 p.extend_from_slice(&1i32.to_be_bytes());
601 p.extend_from_slice(&i32::MAX.to_be_bytes());
602 let mut buf = message(b'v', &p);
603 assert!(decode(&mut buf).is_err());
604 }
605
606 #[test]
607 fn oversized_message_length_is_rejected() {
608 let mut buf = BytesMut::new();
609 buf.extend_from_slice(&[b'D']);
610 buf.extend_from_slice(&i32::MAX.to_be_bytes());
611 match decode(&mut buf) {
612 Err(Error::Decode(msg)) => assert!(msg.contains("exceeds"), "{msg}"),
613 other => panic!("unexpected {other:?}"),
614 }
615 assert_eq!(buf.len(), 5);
617 }
618
619 #[test]
620 fn custom_limit_is_honoured() {
621 let payload = vec![0u8; 1024];
623 let mut buf = message(b'D', &payload);
624 assert!(decode(&mut buf).unwrap().is_some());
625
626 let mut buf = message(b'D', &payload);
627 match decode_with_limit(&mut buf, 100) {
628 Err(Error::Decode(msg)) => assert!(msg.contains("exceeds"), "{msg}"),
629 other => panic!("unexpected {other:?}"),
630 }
631 assert_eq!(buf.len(), 1 + 4 + payload.len());
633
634 let mut buf = message(b'Z', &[b'I']);
636 assert!(decode_with_limit(&mut buf, 5).unwrap().is_some());
637
638 let mut buf = message(b'Z', &[b'I']);
640 assert!(decode_with_limit(&mut buf, 0).is_err());
641 }
642
643 #[test]
644 fn truncated_payloads_error_instead_of_panicking() {
645 let mut buf = message(b'S', b"name-without-nul");
647 assert!(decode(&mut buf).is_err());
648 let mut buf = message(b'C', b"INSERT 0 1");
649 assert!(decode(&mut buf).is_err());
650 let mut buf = message(b'K', &[0, 1]);
652 assert!(decode(&mut buf).is_err());
653 let mut buf = message(b'Z', &[]);
654 assert!(decode(&mut buf).is_err());
655 let mut buf = message(b'A', &[0, 0, 0, 1]);
656 assert!(decode(&mut buf).is_err());
657 let mut p = Vec::new();
659 p.extend_from_slice(&1i16.to_be_bytes());
660 let mut buf = message(b'T', &p);
661 assert!(decode(&mut buf).is_err());
662 }
663
664 #[test]
665 fn error_fields_may_be_non_utf8_or_non_ascii() {
666 let mut payload = Vec::new();
668 payload.extend_from_slice(b"SERROR\0");
669 payload.extend_from_slice("C\u{20ac}\0".as_bytes());
670 payload.extend_from_slice(b"Mweird\0");
671 payload.push(0);
672 let mut buf = message(b'E', &payload);
673 match decode(&mut buf).unwrap_err() {
674 Error::Server(err) => {
675 assert_eq!(err.class(), "");
676 assert_eq!(err.message, "weird");
677 }
678 other => panic!("unexpected {other:?}"),
679 }
680 }
681
682 #[test]
683 fn invalid_utf8_in_identifiers_is_an_error() {
684 let mut payload = Vec::new();
685 payload.extend_from_slice(&1i16.to_be_bytes());
686 payload.extend_from_slice(&[0xff, 0xfe, 0]);
687 let mut buf = message(b'T', &payload);
688 assert!(decode(&mut buf).is_err());
689 }
690
691 #[test]
692 fn invalid_utf8_in_error_fields_is_lossy_not_a_decode_error() {
693 let mut payload = Vec::new();
697 payload.extend_from_slice(b"SERROR\0");
698 payload.extend_from_slice(b"C42601\0");
699 payload.extend_from_slice(&[b'M', 0xff, 0xfe, b'h', 0x00]);
700 payload.push(0);
701 let mut buf = message(b'E', &payload);
702 match decode(&mut buf).unwrap_err() {
703 Error::Server(err) => {
704 assert_eq!(err.code, "42601");
705 assert!(err.message.contains('h'), "message was {:?}", err.message);
706 assert!(err.message.contains('\u{fffd}'), "message was {:?}", err.message);
707 }
708 other => panic!("unexpected {other:?}"),
709 }
710 }
711
712 #[test]
713 fn copy_both_response_is_rejected() {
714 let mut payload = Vec::new();
717 payload.push(1u8);
718 payload.extend_from_slice(&1i16.to_be_bytes());
719 payload.extend_from_slice(&1i16.to_be_bytes());
720 let mut buf = message(b'W', &payload);
721 assert!(matches!(decode(&mut buf), Err(Error::Protocol(_))));
722 }
723
724 #[test]
725 fn data_row_is_zero_copy_slice_of_frame() {
726 let mut payload = Vec::new();
727 payload.extend_from_slice(&1i16.to_be_bytes());
728 payload.extend_from_slice(&3i32.to_be_bytes());
729 payload.extend_from_slice(&[7, 8, 9]);
730 let mut buf = message(b'D', &payload);
731 match decode(&mut buf).unwrap().unwrap() {
732 BackendMessage::DataRow(bytes) => {
733 assert_eq!(bytes.len(), payload.len());
734 }
735 other => panic!("unexpected {other:?}"),
736 }
737 }
738}