sdk: Fix reading strings
Fatshark has a few weird string fields, where they provide a length field, but then sometimes write a shorter, NUL-terminated string into that same field and adding padding up to the "advertised" length. To properly read those strings, we can't rely on just the length field anymore, but need to check for a NUL, too.
This commit is contained in:
parent
edad0d4493
commit
08219f05ba
1 changed files with 21 additions and 14 deletions
|
@ -43,6 +43,7 @@ impl<T: FromBinary> FromBinary for Vec<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod sync {
|
pub mod sync {
|
||||||
|
use std::ffi::CStr;
|
||||||
use std::io::{self, Read, Seek, SeekFrom};
|
use std::io::{self, Read, Seek, SeekFrom};
|
||||||
|
|
||||||
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
||||||
|
@ -165,25 +166,13 @@ pub mod sync {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_string_len(&mut self, len: usize) -> Result<String> {
|
fn read_string_len(&mut self, len: usize) -> Result<String> {
|
||||||
let mut buf = vec![0; len];
|
let pos = self.stream_position();
|
||||||
let res = self
|
|
||||||
.read_exact(&mut buf)
|
|
||||||
.map_err(Report::new)
|
|
||||||
.and_then(|_| {
|
|
||||||
String::from_utf8(buf).map_err(|err| {
|
|
||||||
let ascii = String::from_utf8_lossy(err.as_bytes()).to_string();
|
|
||||||
let bytes = format!("{:?}", err.as_bytes());
|
|
||||||
Report::new(err)
|
|
||||||
.with_section(move || bytes.header("Bytes:"))
|
|
||||||
.with_section(move || ascii.header("ASCII:"))
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
|
let res = read_string_len(self, len);
|
||||||
if res.is_ok() {
|
if res.is_ok() {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pos = self.stream_position();
|
|
||||||
if pos.is_ok() {
|
if pos.is_ok() {
|
||||||
res.with_section(|| {
|
res.with_section(|| {
|
||||||
format!("{pos:#X} ({pos})", pos = pos.unwrap()).header("Position: ")
|
format!("{pos:#X} ({pos})", pos = pos.unwrap()).header("Position: ")
|
||||||
|
@ -243,4 +232,22 @@ pub mod sync {
|
||||||
|
|
||||||
Err(err).with_section(|| format!("{pos:#X} ({pos})").header("Position: "))
|
Err(err).with_section(|| format!("{pos:#X} ({pos})").header("Position: "))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_string_len(mut r: impl Read, len: usize) -> Result<String> {
|
||||||
|
let mut buf = vec![0; len];
|
||||||
|
r.read_exact(&mut buf)
|
||||||
|
.wrap_err_with(|| format!("Failed to read {} bytes", len))?;
|
||||||
|
|
||||||
|
let res = match CStr::from_bytes_until_nul(&buf) {
|
||||||
|
Ok(s) => {
|
||||||
|
let s = s.to_str()?;
|
||||||
|
Ok(s.to_string())
|
||||||
|
}
|
||||||
|
Err(_) => String::from_utf8(buf.clone()).map_err(Report::new),
|
||||||
|
};
|
||||||
|
|
||||||
|
res.wrap_err("Invalid binary for UTF8 string")
|
||||||
|
.with_section(|| format!("{}", String::from_utf8_lossy(&buf)).header("ASCI:"))
|
||||||
|
.with_section(|| format!("{:x?}", buf).header("Bytes:"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue