]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
dcerpc: fix integer underflow
authorPhilippe Antoine <pantoine@oisf.net>
Fri, 23 Sep 2022 09:01:03 +0000 (11:01 +0200)
committerVictor Julien <vjulien@oisf.net>
Sun, 27 Nov 2022 06:22:24 +0000 (07:22 +0100)
as input.len() can be 65536, it cannot be directly cast to u16

Ticket: #5557
Ticket: #5602

rust/src/dcerpc/dcerpc.rs

index 9f01178cbfa869cfe58a9822d0424db1c87430dd..07af91ec05f47332ae44bb7e52b96add315ad1c3 100644 (file)
@@ -793,7 +793,7 @@ impl DCERPCState {
         }
     }
 
-    pub fn handle_stub_data(&mut self, input: &[u8], input_len: u16, dir: u8) -> u16 {
+    pub fn handle_stub_data(&mut self, input: &[u8], input_len: usize, dir: u8) -> u16 {
         let retval;
         let hdrpfcflags = self.get_hdr_pfcflags().unwrap_or(0);
         let padleft = self.padleft;
@@ -871,19 +871,20 @@ impl DCERPCState {
     /// Return value:
     /// * Success: Number of bytes successfully parsed.
     /// * Failure: -1 in case fragment length defined by header mismatches the data.
-    pub fn handle_common_stub(&mut self, input: &[u8], bytes_consumed: u16, dir: u8) -> i32 {
+    pub fn handle_common_stub(&mut self, input: &[u8], bytes_consumed: usize, dir: u8) -> i32 {
         let fraglen = self.get_hdr_fraglen().unwrap_or(0);
-        if fraglen < bytes_consumed as u16 + DCERPC_HDR_LEN {
+        if (fraglen as usize) < bytes_consumed + (DCERPC_HDR_LEN as usize) {
             return -1;
         }
-        self.padleft = fraglen - DCERPC_HDR_LEN - bytes_consumed;
-        let mut input_left = input.len() as u16 - bytes_consumed;
+        // Above check makes sure padleft stays in u16 limits
+        self.padleft = fraglen - DCERPC_HDR_LEN - bytes_consumed as u16;
+        let mut input_left = input.len() - bytes_consumed;
         let mut parsed = bytes_consumed as i32;
         while input_left > 0 && parsed < fraglen as i32 {
             let retval = self.handle_stub_data(&input[parsed as usize..], input_left, dir);
-            if retval > 0 && retval <= input_left {
+            if retval > 0 && retval as usize <= input_left {
                 parsed += retval as i32;
-                input_left -= retval;
+                input_left -= <u16 as std::convert::Into<usize>>::into(retval);
             } else if input_left > 0 {
                 SCLogDebug!(
                     "Error parsing DCERPC {} stub data",
@@ -925,7 +926,7 @@ impl DCERPCState {
                 }
                 let parsed = self.handle_common_stub(
                     &input,
-                    (input.len() - leftover_input.len()) as u16,
+                    input.len() - leftover_input.len(),
                     core::STREAM_TOSERVER,
                 );
                 parsed
@@ -1125,12 +1126,12 @@ impl DCERPCState {
 }
 
 fn evaluate_stub_params(
-    input: &[u8], input_len: u16, hdrflags: u8, lenleft: u16,
+    input: &[u8], input_len: usize, hdrflags: u8, lenleft: u16,
     stub_data_buffer: &mut Vec<u8>,stub_data_buffer_reset: &mut bool,
 ) -> u16 {
-    let stub_len: u16;
     let fragtype = hdrflags & (PFC_FIRST_FRAG | PFC_LAST_FRAG);
-    stub_len = cmp::min(lenleft, input_len);
+    // min of usize and u16 is a valid u16
+    let stub_len: u16 = cmp::min(lenleft as usize, input_len) as u16;
     if stub_len == 0 {
         return 0;
     }