#![no_main] use libfuzzer_sys::fuzz_target; use typst::diag::{FileError, FileResult}; use typst::eval::Tracer; use typst::foundations::{Bytes, Datetime}; use typst::syntax::{FileId, Source}; use typst::text::{Font, FontBook}; use typst::utils::LazyHash; use typst::visualize::Color; use typst::{Library, World}; struct FuzzWorld { library: LazyHash, book: LazyHash, font: Font, source: Source, } impl FuzzWorld { fn new(text: &str) -> Self { let data = typst_assets::fonts().next().unwrap(); let font = Font::new(Bytes::from_static(data), 0).unwrap(); let book = FontBook::from_fonts([&font]); Self { library: LazyHash::new(Library::default()), book: LazyHash::new(book), font, source: Source::detached(text), } } } impl World for FuzzWorld { fn library(&self) -> &LazyHash { &self.library } fn book(&self) -> &LazyHash { &self.book } fn main(&self) -> Source { self.source.clone() } fn source(&self, src: FileId) -> FileResult { Err(FileError::NotFound(src.vpath().as_rootless_path().into())) } fn file(&self, src: FileId) -> FileResult { Err(FileError::NotFound(src.vpath().as_rootless_path().into())) } fn font(&self, _: usize) -> Option { Some(self.font.clone()) } fn today(&self, _: Option) -> Option { None } } fuzz_target!(|text: &str| { let world = FuzzWorld::new(text); let mut tracer = Tracer::new(); if let Ok(document) = typst::compile(&world, &mut tracer) { if let Some(page) = document.pages.first() { std::hint::black_box(typst_render::render(&page.frame, 1.0, Color::WHITE)); } } comemo::evict(10); });