From e8e4b0ba48a5458684df1182c329d2b5ec6abd49 Mon Sep 17 00:00:00 2001 From: c <c@farsight.net> Date: Tue, 12 Nov 2024 11:23:21 +0100 Subject: [PATCH 1/3] test: add xls with malformed format --- tests/malformed_format.xls | Bin 0 -> 15872 bytes tests/test.rs | 5 +++++ 2 files changed, 5 insertions(+) create mode 100644 tests/malformed_format.xls diff --git a/tests/malformed_format.xls b/tests/malformed_format.xls new file mode 100644 index 0000000000000000000000000000000000000000..ee87abd077e57cbb8e982052e0ba10d7eee52d6f GIT binary patch literal 15872 zcmeHOU2I&(bw0b?C3pF^%jK_@KfAFdTb5*-a${F@Rg0uVDKbP+k>mggjMPh-ve)I0 zN-Yi7Xj7(*-`t-hh}s7ONf0+h(IRMIAV`5KV&0MhL4pD)&;kM2x)1G3;TG+KfyV6j zopWb*cJ^}3xPGzWE8V-ZXU>_K^UcipX67z`^5cQsuYbGv&k|g}Djo99URF9ic>?JP z_dPFi2x-dR+1uN5VkAGhK0pZkJZftPIxvMhjhlVmg*$^gi@O_l5AI&veYpE^=Wt^P z$N=sF?m^r`xQB6%;2y<2hMQx9_jr_^j6Od=5PhhddQ~>?uO?-gmvww@%5R~E4t|Yb z#P|Rm#L|x!2ho2wosa5oAn<NjG2h2Oo53tkr)4$!!!DA*_a%wvUEDjk{{{Ec7#pdx zmDT0){?{C={x$U)p8fJ`8V_JNBjr>0AV)lfFD&;D^m&gy`|(W3KWX|TV#g1VzxTU; zOhSQbdUmr~S#8Mwmgcy8dD7{}$m8_u<u~cSg>P9={r&2#%coM^^15_gn7=%Kb@tL! zDkFa;>4k-dKmF;cR7$=ni5Y7AxpXZoEIeI4cWzf><m>W3du7=vqas|C(Mibu``u)8 zI@F7kvD{GagDHC**o0Uer*CgHWA#9c>_m+0Sd1*&A`|o~>S*dC%08JW<o$X((ch5$ zc4l&RYi;ZCN%m!z>7Cjs&(zjxkN0@8m-+@~YYST=suz{_((PP}Y?`)CuM6Xdb;Q`- z{9<>*whQAd)bra?joK2`t94wAX^WHj<vCeotM!JmQ}DydqI%U|Cv	a|wB%_PCCF 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 literal 0 HcmV?d00001 diff --git a/tests/test.rs b/tests/test.rs index 4faf6b7..bad9c3c 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -2138,3 +2138,8 @@ fn test_string_ref() { // second sheet is the same with a cell reference to the first sheet range_eq!(xlsx.worksheet_range_at(1).unwrap().unwrap(), expected_range); } + +#[test] +fn test_malformed_format() { + let _xls: Xls<_> = wb("malformed_format.xls"); +} From 3ee78831dd8338d17b64b74968c8dc91b3208394 Mon Sep 17 00:00:00 2001 From: c <c@farsight.net> Date: Tue, 12 Nov 2024 11:26:05 +0100 Subject: [PATCH 2/3] fix: expand length check to cover index 4 into slice, fixing panic with malformed formats --- src/xls.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/xls.rs b/src/xls.rs index a04fcbe..afa6069 100644 --- a/src/xls.rs +++ b/src/xls.rs @@ -910,17 +910,19 @@ fn parse_xf(r: &Record<'_>) -> Result<u16, XlsError> { /// Decode Format /// /// See: https://learn.microsoft.com/ru-ru/openspecs/office_file_formats/ms-xls/300280fd-e4fe-4675-a924-4d383af48d3b +/// 2.4.126 fn parse_format(r: &mut Record<'_>, encoding: &XlsEncoding) -> Result<(u16, CellFormat), XlsError> { - if r.data.len() < 4 { + if r.data.len() < 5 { return Err(XlsError::Len { typ: "format", - expected: 4, + expected: 5, found: r.data.len(), }); } let idx = read_u16(r.data); + // TODO: check if this can be replaced with parse_string() let cch = read_u16(&r.data[2..]) as usize; let high_byte = r.data[4] & 0x1 != 0; r.data = &r.data[5..]; From b5a8bf591b254c3c00c047b4b8699d95cc8278b4 Mon Sep 17 00:00:00 2001 From: c <c@farsight.net> Date: Tue, 12 Nov 2024 11:29:47 +0100 Subject: [PATCH 3/3] fix: skip malformed formats --- src/xls.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/xls.rs b/src/xls.rs index afa6069..47e080a 100644 --- a/src/xls.rs +++ b/src/xls.rs @@ -338,9 +338,11 @@ impl<RS: Read + Seek> Xls<RS> { self.is_1904 = true } } - // FORMATTING + // 2.4.126 FORMATTING 0x041E => { - let (idx, format) = parse_format(&mut r, &encoding)?; + let Ok((idx, format)) = parse_format(&mut r, &encoding) else { + continue; + }; formats.insert(idx, format); } // XFS