From 13afa37768acf9b142b58d1e62b17b1cc71dd0f4 Mon Sep 17 00:00:00 2001 From: Yevhenii Reizner Date: Fri, 9 Sep 2022 19:45:40 +0300 Subject: [PATCH] (loca) Allow incomplete table. --- CHANGELOG.md | 1 + src/tables/loca.rs | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c86351bf..83ff26fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - (hmtx/vmtx) Allow missing additional side bearings. +- (loca) Allow incomplete table. - Reduce strictness of some table length checks. ## [0.15.2] - 2022-06-17 diff --git a/src/tables/loca.rs b/src/tables/loca.rs index 571183fe..31857f8f 100644 --- a/src/tables/loca.rs +++ b/src/tables/loca.rs @@ -3,6 +3,7 @@ use core::num::NonZeroU16; use core::ops::Range; +use core::convert::TryFrom; use crate::{GlyphId, IndexToLocationFormat}; use crate::parser::{Stream, LazyArray16, NumFrom}; @@ -29,12 +30,26 @@ impl<'a> Table<'a> { // The number of ranges is `maxp.numGlyphs + 1`. // // Check for overflow first. - let total = if number_of_glyphs.get() == core::u16::MAX { + let mut total = if number_of_glyphs.get() == core::u16::MAX { number_of_glyphs.get() } else { number_of_glyphs.get() + 1 }; + // By the spec, the number of `loca` offsets is `maxp.numGlyphs + 1`. + // But some malformed fonts can have less glyphs than that. + // In which case we try to parse only the available offsets + // and do not return an error, since the expected data length + // would go beyond table's length. + // + // In case when `loca` has more data than needed we simply ignore the rest. + let actual_total = match format { + IndexToLocationFormat::Short => data.len() / 2, + IndexToLocationFormat::Long => data.len() / 4, + }; + let actual_total = u16::try_from(actual_total).ok()?; + total = total.min(actual_total); + let mut s = Stream::new(data); match format { IndexToLocationFormat::Short => {