Correctly handle result data bounds
This commit is contained in:
		@@ -483,21 +483,34 @@ impl ImprovDataFromPacket for RPCResultPacket {
 | 
				
			|||||||
            return Err(anyhow!("Packet is not RPCResult"));
 | 
					            return Err(anyhow!("Packet is not RPCResult"));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Byte 1
 | 
				
			||||||
 | 
					        let command_responded_to = RPCCommand::try_from(&raw_packet.data[0]).context("Failed to determine RPC command this packet responds to")?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Byte 2
 | 
				
			||||||
 | 
					        let result_data_len = usize::from(raw_packet.data[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Byte 3...
 | 
				
			||||||
 | 
					        // slice the part of the raw_packet data that contains the result strings
 | 
				
			||||||
 | 
					        let result_data = &raw_packet.data[2..result_data_len+2];
 | 
				
			||||||
 | 
					        // the ESPHome implementation has a trailing nullbyte after the strings, so result_data
 | 
				
			||||||
 | 
					        // ends before raw_packet.data, everything after that is ignored
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // store result strings
 | 
				
			||||||
        let mut results: Vec<String> = Vec::new();
 | 
					        let mut results: Vec<String> = Vec::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut data_position: usize = 2;
 | 
					        let mut data_position: usize = 0;
 | 
				
			||||||
        loop {
 | 
					        loop {
 | 
				
			||||||
            if data_position >= raw_packet.data.len() {
 | 
					            if data_position >= result_data.len() {
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // find string bounds
 | 
					            // find string bounds
 | 
				
			||||||
            let current_string_len: usize = usize::from(raw_packet.data[data_position]);
 | 
					            let current_string_len: usize = usize::from(result_data[data_position]);
 | 
				
			||||||
            let current_string_begin = data_position + 1;
 | 
					            let current_string_begin = data_position + 1;
 | 
				
			||||||
            let current_string_end = data_position + current_string_len;
 | 
					            let current_string_end = data_position + current_string_len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // load string and append to results
 | 
					            // load string and append to results
 | 
				
			||||||
            let string_bytes = &raw_packet.data[current_string_begin..current_string_end+1];
 | 
					            let string_bytes = &result_data[current_string_begin..current_string_end+1];
 | 
				
			||||||
            let string = std::str::from_utf8(string_bytes).context("Failed to convert response to UTF-8 string")?.to_string();
 | 
					            let string = std::str::from_utf8(string_bytes).context("Failed to convert response to UTF-8 string")?.to_string();
 | 
				
			||||||
            results.push(string);
 | 
					            results.push(string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -506,7 +519,7 @@ impl ImprovDataFromPacket for RPCResultPacket {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return Ok(Self {
 | 
					        return Ok(Self {
 | 
				
			||||||
            command_responded_to: RPCCommand::try_from(&raw_packet.data[0]).context("Failed to determine RPC command this packet responds to")?,
 | 
					            command_responded_to: command_responded_to,
 | 
				
			||||||
            results: results,
 | 
					            results: results,
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user