Repository: inspektor-dev/inspektor (language: rust)

Issue:
no context error message. 
Error message given by the postgres is not parsed correctly and forwarded to the client. 

Instead of forwarding the correct error message, the inspektor just sends `ERROR` without any context.


Discussion / hints:

Fix patch:
diff --git a/src/postgres_driver/message.rs b/src/postgres_driver/message.rs
index 42002c1..89f835c 100644
--- a/src/postgres_driver/message.rs
+++ b/src/postgres_driver/message.rs
@@ -47,7 +47,7 @@ impl TransactionStatus {
 
 #[derive(Debug)]
 pub enum BackendMessage {
-    ErrorMsg(Option<String>),
+    ErrorMsg(u8,Option<String>),
     AuthenticationOk { success: bool },
     AuthenticationCleartextPassword,
     AuthenticationMD5Password { salt: Vec<u8> },
@@ -78,18 +78,13 @@ impl BackendMessage {
                 buf.put_u32(1);
                 buf
             }
-            BackendMessage::ErrorMsg(msg) => {
+            BackendMessage::ErrorMsg(code,msg) => {
                 buf.put_u8(b'E');
                 write_message(&mut buf, |buf| {
+                    buf.put_u8(*code);
                     if let Some(msg) = msg {
-                        buf.put_u8(b'S');
-                        write_cstr(buf, "ERROR".to_string().as_bytes())?;
-                        buf.put_u8(b'C');
-                        write_cstr(buf, "42501".to_string().as_bytes())?;
-                        buf.put_u8(b'M');
-                        write_cstr(buf, msg.as_bytes())?;
+                        buf.put_slice(msg.as_bytes());
                     }
-                    buf.put_u8(b'\0');
                     Ok(())
                 })
                 .unwrap();
@@ -170,12 +165,19 @@ where
             }
         }
         b'E' => {
-            if buf[0] == 0 {
-                return Ok(BackendMessage::ErrorMsg(None));
+            let code= buf[0];
+            if code == 0 {
+                return Ok(BackendMessage::ErrorMsg(code,None));
             }
             buf.advance(1);
-            let err_msg = read_cstr(&mut buf)?;
-            return Ok(BackendMessage::ErrorMsg(Some(err_msg)));
+            // it's safe to convert remaining byte to string since 
+            // from now on we have only bytes related to string.
+            
+            let err_msg = std::str::from_utf8(&buf[..buf.remaining()])
+            .map_err(|_| anyhow!("error while reading cstr"))?
+            .to_string();
+
+            return Ok(BackendMessage::ErrorMsg(code,Some(err_msg)));
         }
         b'Z' => {
             let state = TransactionStatus::from_u8(buf[0]);
diff --git a/src/postgres_driver/protocol_handler.rs b/src/postgres_driver/protocol_handler.rs
index 3110601..88aa70a 100644
--- a/src/postgres_driver/protocol_handler.rs
+++ b/src/postgres_driver/protocol_handler.rs
@@ -244,7 +244,7 @@ impl ProtocolHandler {
                                     BackendMessage::ReadyForQuery{..} => {
                                         // send the pending error message.
                                         let e = self.pending_error.as_ref().unwrap();
-                                        let err_rsp = BackendMessage::ErrorMsg(Some(format!("{}", e)));
+                                        let err_rsp = BackendMessage::ErrorMsg(b'S',Some(format!("{}", e)));
                                         if let Err(e) = self.client_conn.write_all(&err_rsp.encode()).await{
                                             error!("error while writing the rsp message to the client {:?}", e);
                                             return Ok(());
@@ -283,7 +283,7 @@ impl ProtocolHandler {
                             let ctx =  Ctx::new(table_info.column_relation.clone());
                             if let Err(e) = self.handle_frontend_message(&mut msg, ctx, table_info.schemas.clone()).await{
                                 error!("error while handling frontend message {:?}", e);
-                                let rsp = BackendMessage::ErrorMsg(Some(format!("{}", e)));
+                                let rsp = BackendMessage::ErrorMsg(b'S',Some(format!("{}", e)));
                                 if let Err(e) = self.client_conn.write_all(&rsp.encode()).await{
                                     error!("error while writing the rsp message to the client {:?}", e);
                                     return Ok(());


Test patch: