Tolerate trailing or missing null bytes at end of decompressed CELL record data
Fixes some crashes when dealing with wierd decompressed CELL data. More details here: https://en.uesp.net/wiki/Skyrim_Mod_talk:Mod_File_Format/CELL#Trailing_or_missing_null_bytes_at_end_of_decompressed_CELL_data
This commit is contained in:
parent
4f70f90d2b
commit
5e3a07dfa6
@ -7,6 +7,8 @@ use std::{convert::TryInto, str};
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use encoding_rs::WINDOWS_1252;
|
use encoding_rs::WINDOWS_1252;
|
||||||
use flate2::read::ZlibDecoder;
|
use flate2::read::ZlibDecoder;
|
||||||
|
use nom::combinator::rest;
|
||||||
|
use nom::error::ParseError;
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::{take, take_while},
|
bytes::complete::{take, take_while},
|
||||||
@ -502,13 +504,22 @@ fn parse_cell_fields<'a>(input: &'a [u8]) -> IResult<&'a [u8], CellData> {
|
|||||||
input = remaining;
|
input = remaining;
|
||||||
large_size = Some(size);
|
large_size = Some(size);
|
||||||
}
|
}
|
||||||
|
"\0\0\0\0" => {
|
||||||
|
// Some plugins have 8-9 bytes of trailing null bytes in the decompressed interior CELL data
|
||||||
|
// This detects and skips those null bytes
|
||||||
|
let (remaining, _) = take_while(|c| c == b'\0')(input)?;
|
||||||
|
input = remaining;
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(size) = large_size {
|
if let Some(size) = large_size {
|
||||||
let (remaining, _) = take(size)(input)?;
|
let (remaining, _) = take(size)(input)?;
|
||||||
input = remaining;
|
input = remaining;
|
||||||
large_size = None;
|
large_size = None;
|
||||||
} else {
|
} else {
|
||||||
let (remaining, _) = take(field.size)(input)?;
|
// Some plugins have decompressed cell data that is short 1-2 bytes and the parser is supposed
|
||||||
|
// to substitute zero bytes there. Since we are not actually reading the fields at the end of
|
||||||
|
// the CELL records, we just skip over the remaining bytes if the full 4 are not there.
|
||||||
|
let (remaining, _) = alt((take(field.size), rest))(input)?;
|
||||||
input = remaining;
|
input = remaining;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user