Panic: debug_assert in SubroutineCollection::new on a CID-keyed font with 256 Font DICTs
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 74/100
Direzione di ricerca
Inizia da subsetter-0.2.6/src/cff/subroutines.rs, in particolare da SubroutineCollection::new e dal percorso get_handler, poi segui come viene rappresentato il conteggio di FDArray. Esegui il reproducer fornito oppure aggiungi un test di regressione per 256 Font DICT. Il lavoro è completato quando un font valido con 256 Font DICT non causa più un panic nelle build di debug e i conteggi non supportati vengono gestiti senza panic.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
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.
- Lingua principale
- Rust
- Stelle
- 61
- Fork
- 16
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di typst/subsetter
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
-
head table bounding box is not recalculated for variable font instancesForse già presa @khaledhosny l’ha presa 16 giorni fa. Aperta
Difficoltà 3/5 1-2 giorni Idoneità per principianti 56/100
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 45/100
-
Difficoltà 3/5 Mezza giornata Idoneità per principianti 67/100
Tutte le issue di typst/subsetter
Issue simili
-
Input: placeholder drawn in the text colour when the empty Input is focused but not yet editedAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
pierreaubert/gpui-toolkit#114 ·
I maintainer di solito rispondono entro 1 giorno
-
BibLaTeX `type` keys like `phdthesis`, `mathesis`, `techreport` are printed raw instead of localizedAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
-
remove the use of `forget`Apertagood first issue help wanted
Difficoltà 2/5 1-3 ore Idoneità per principianti 80/100
I maintainer di solito rispondono entro 1 giorno
-
compiler
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
HerringtonDarkholme/hd-lang#1853 ·
I maintainer di solito rispondono entro 1 giorno
-
bug needs triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
pbakaus/impeccable#1462 ·
I maintainer di solito rispondono entro 1 giorno