Skip to content

Commit

Permalink
Merge branch 'main' into scaler-refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
dfrg committed Dec 11, 2024
2 parents 2b2a7cb + 67ef9ea commit e682f0a
Show file tree
Hide file tree
Showing 11 changed files with 542 additions and 393 deletions.
29 changes: 26 additions & 3 deletions read-fonts/src/tables/glyf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ impl PointCoord for F26Dot6 {
fn midpoint(self, other: Self) -> Self {
// FreeType uses integer division on 26.6 to compute midpoints.
// See: https://github.com/freetype/freetype/blob/de8b92dd7ec634e9e2b25ef534c54a3537555c11/src/base/ftoutln.c#L123
Self::from_bits((self.to_bits() + other.to_bits()) / 2)
Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
}
}

Expand All @@ -780,7 +780,7 @@ impl PointCoord for Fixed {
}

fn midpoint(self, other: Self) -> Self {
Self::from_bits((self.to_bits() + other.to_bits()) / 2)
Self::from_bits(midpoint_i32(self.to_bits(), other.to_bits()))
}
}

Expand All @@ -798,10 +798,20 @@ impl PointCoord for i32 {
}

fn midpoint(self, other: Self) -> Self {
(self + other) / 2
midpoint_i32(self, other)
}
}

// Midpoint function that avoids overflow on large values.
fn midpoint_i32(a: i32, b: i32) -> i32 {
// Original overflowing code was: (a + b) / 2
// Choose wrapping arithmetic here because we shouldn't ever
// hit this outside of fuzzing or broken fonts _and_ this is
// called from the outline to path conversion code which is
// very performance sensitive
a.wrapping_add(b.wrapping_sub(a) / 2)
}

impl PointCoord for f32 {
fn from_fixed(x: Fixed) -> Self {
x.to_f32()
Expand Down Expand Up @@ -1023,4 +1033,17 @@ mod tests {
]
);
}

// Minimized test case from https://issues.oss-fuzz.com/issues/382732980
// Add with overflow when computing midpoint of 1084092352 and 1085243712
// during outline -> path conversion
#[test]
fn avoid_midpoint_overflow() {
let a = F26Dot6::from_bits(1084092352);
let b = F26Dot6::from_bits(1085243712);
let expected = a.to_bits() + (b.to_bits() - a.to_bits()) / 2;
// Don't panic!
let midpoint = a.midpoint(b);
assert_eq!(midpoint.to_bits(), expected);
}
}
13 changes: 12 additions & 1 deletion read-fonts/src/tables/variations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ impl Iterator for PackedPointNumbersIter<'_> {
return None;
}
self.seen += 1;
self.last_val += self.current_run.next()?;
self.last_val = self.last_val.checked_add(self.current_run.next()?)?;
Some(self.last_val)
}

Expand Down Expand Up @@ -1491,4 +1491,15 @@ mod tests {
let expected_len = 2 * row_len;
assert_eq!(ivs.delta_sets().len(), expected_len);
}

// Add with overflow when accumulating packed point numbers
// https://issues.oss-fuzz.com/issues/378159154
#[test]
fn packed_point_numbers_avoid_overflow() {
// Lots of 1 bits triggers the behavior quite nicely
let buf = vec![0xFF; 0xFFFF];
let iter = PackedPointNumbersIter::new(0xFFFF, FontData::new(&buf).cursor());
// Don't panic!
let _ = iter.count();
}
}
Loading

0 comments on commit e682f0a

Please sign in to comment.