Panic: debug_assert in SubroutineCollection::new on a CID-keyed font with 256 Font DICTs
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 74/100
Línea de trabajo
Empieza con subsetter-0.2.6/src/cff/subroutines.rs, especialmente con SubroutineCollection::new y la ruta de get_handler, y luego sigue cómo se representa el recuento de FDArray. Ejecuta el reproducer proporcionado o añade una prueba de regresión para 256 Font DICTs. Se considera terminado cuando una fuente válida con 256 Font DICTs ya no provoca un panic en las compilaciones de depuración y los recuentos no compatibles se gestionan sin panic.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
subset panics on a CID-keyed CFF font with 256 Font DICTs, in any build with debug assertions (debug builds, cargo test, fuzzing):
thread 'main' panicked at subsetter-0.2.6/src/cff/subroutines.rs:11:9:
assertion failed: subroutines.len() <= 255
SubroutineCollection::new asserts that there are at most 255 local subroutine lists, one per Font DICT. FDSelect gives each glyph's Font DICT as a Card8 (Technical Note #5176, FDSelect formats 0 and 3), so indices 0 to 255 address 256 Font DICTs, and a font with 256 is well formed. Without debug assertions subset returns Ok. This happens with 0.2.6 and with main (b0adcc1).
To reproduce with subsetter 0.2.6 (default-features = false). The font is built in code for this report:
/// A CFF INDEX of `items`.
fn index(items: &[Vec<u8>]) -> Vec<u8> {
if items.is_empty() {
return vec![0, 0];
}
let mut offsets = vec![1u32];
for item in items {
offsets.push(offsets.last().unwrap() + item.len() as u32);
}
let size = (1..=4u8).find(|&size| *offsets.last().unwrap() < 1 << (8 * size as u32)).unwrap();
let mut out = (items.len() as u16).to_be_bytes().to_vec();
out.push(size);
for offset in offsets {
out.extend(&offset.to_be_bytes()[4 - size as usize..]);
}
items.iter().for_each(|item| out.extend(item));
out
}
/// A DICT integer operand in five bytes.
fn int5(value: i32) -> Vec<u8> {
[&[29u8][..], &value.to_be_bytes()].concat()
}
/// A minimal OpenType font whose CFF table is CID-keyed: one glyph (.notdef, endchar)
/// and an FDArray of `count` Font DICTs, all pointing at one empty Private DICT. FDSelect
/// (format 0) puts the glyph in Font DICT 0.
fn font(count: usize) -> Vec<u8> {
let header = vec![1, 0, 4, 1];
let names = index(&[b"A".to_vec()]);
let strings = index(&[b"Adobe".to_vec(), b"Identity".to_vec()]);
let gsubrs = index(&[]);
let charstrings = index(&[vec![14]]);
let fdselect = vec![0, 0];
let top = |charstrings_at: i32, fdarray_at: i32, fdselect_at: i32| {
[
int5(391), int5(392), int5(0), vec![12, 30], // ROS Adobe-Identity-0
int5(charstrings_at), vec![17],
int5(fdarray_at), vec![12, 36],
int5(fdselect_at), vec![12, 37],
]
.concat()
};
let font_dict = |private_at: i32| [int5(0), int5(private_at), vec![18]].concat();
let top_len = index(&[top(0, 0, 0)]).len();
let fdarray_len = index(&vec![font_dict(0); count]).len();
let charstrings_at = header.len() + names.len() + top_len + strings.len() + gsubrs.len();
let fdselect_at = charstrings_at + charstrings.len();
let fdarray_at = fdselect_at + fdselect.len();
let private_at = fdarray_at + fdarray_len;
let top = index(&[top(charstrings_at as i32, fdarray_at as i32, fdselect_at as i32)]);
let fdarray = index(&vec![font_dict(private_at as i32); count]);
let cff = [header, names, top, strings, gsubrs, charstrings, fdselect, fdarray].concat();
let mut font = b"OTTO".to_vec();
for value in [1u16, 16, 0, 0] {
font.extend(value.to_be_bytes());
}
font.extend(b"CFF ");
for value in [0u32, 28, cff.len() as u32] {
font.extend(value.to_be_bytes());
}
font.extend(cff);
font
}
fn main() {
for count in [255, 256] {
let data = font(count);
let remapper = subsetter::GlyphRemapper::new();
println!("{count} Font DICTs: {:?}", subsetter::subset(&data, 0, &remapper).map(|font| font.len()));
}
}
cargo run prints 255 Font DICTs: Ok(156) and then panics as above; cargo run --release prints Ok(156) for both.
It was found while reviewing how officewright guards against subsetter panics; until it is fixed, our call to subset turns the panic into an error.
A possible fix: assert subroutines.len() <= 256, or, since get_handler takes a u8, return a CFFError for an FDArray of more than 256 Font DICTs instead of asserting.
- Lenguaje dominante
- Rust
- Estrellas
- 61
- Forks
- 16
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de typst/subsetter
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 83/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
-
head table bounding box is not recalculated for variable font instancesPosiblemente ocupada @khaledhosny la tomó hace 16 días. Abierto
Dificultad 3/5 1-2 días Aptitud para principiantes 56/100
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 45/100
-
Dificultad 3/5 Medio día Aptitud para principiantes 67/100
Todos los issues de typst/subsetter
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
Input: placeholder drawn in the text colour when the empty Input is focused but not yet editedAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
pierreaubert/gpui-toolkit#114 ·
Los mantenedores suelen responder en 1 día
-
BibLaTeX `type` keys like `phdthesis`, `mathesis`, `techreport` are printed raw instead of localizedAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
-
remove the use of `forget`Abiertogood first issue help wanted
Dificultad 2/5 1-3 horas Aptitud para principiantes 80/100
Los mantenedores suelen responder en 1 día
-
compiler
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
HerringtonDarkholme/hd-lang#1853 ·
Los mantenedores suelen responder en 1 día