#821: text.loadFont reads at most MAX_FONT_FILE (the font scan's 256 MiB cap)

This commit is contained in:
bflatastic
2026-10-19 23:44:08 +07:00
parent b8aa1ef8f0
commit 203ec13e03
3 changed files with 10 additions and 6 deletions
+2 -4
View File
@@ -362,15 +362,13 @@ fn free_spot(s: &Session, w: f64, h: f64) -> Result<(f64, f64)> {
})
}
/// The bytes of the file at `path`, within the session's allowed file roots.
#[cfg(not(target_arch = "wasm32"))]
pub(super) fn read_path(path: &str) -> Result<Vec<u8>> {
fn read_path(path: &str) -> Result<Vec<u8>> {
crate::file_access::read(path)
}
/// The browser has no files to read: always an error.
#[cfg(target_arch = "wasm32")]
pub(super) fn read_path(path: &str) -> Result<Vec<u8>> {
fn read_path(path: &str) -> Result<Vec<u8>> {
Err(crate::EngineError::Other(format!("{path}: files can't be read in the browser")))
}
+1 -1
View File
@@ -497,7 +497,7 @@ pub fn specs() -> Vec<CommandSpec> {
let b64 = b64.split_once(',').map(|(_, d)| d.to_string()).unwrap_or(b64);
base64::engine::general_purpose::STANDARD.decode(b64.trim()).map_err(|e| bad(cmd, format!("`data`: {e}")))?
} else if let Some(path) = string(p, "path") {
super::create::read_path(&path)?
super::file::read_capped(&path, figcraft_text::fontdb::MAX_FONT_FILE)?
} else {
return Err(bad(cmd, "pass `path` or `data` (base64)"));
};
+7 -1
View File
@@ -819,13 +819,19 @@ fn scan_dir(dir: &std::path::Path, depth: usize, out: &mut BTreeMap<String, (Str
// Very large files are indexed all the same (Apple Color Emoji is ~180 MB and is where the
// system's colour emoji live): `index_bytes` reads headers and name tables out of a zeroed
// buffer, so only those parts are ever touched.
let Some(bytes) = usize::try_from(meta.len()).ok().filter(|l| *l <= 256 * 1024 * 1024).and_then(|l| index_bytes(&path, l)) else { continue };
if meta.len() > MAX_FONT_FILE {
continue;
}
let Some(bytes) = usize::try_from(meta.len()).ok().and_then(|l| index_bytes(&path, l)) else { continue };
for (index, family, style) in faces_in(&bytes) {
out.entry(family.to_lowercase()).or_insert_with(|| (family.clone(), Vec::new())).1.push(Pending { path: path.clone(), index, style });
}
}
}
/// The largest font file read (CJK collections run to ~120 MB, Apple Color Emoji ~180 MB).
pub const MAX_FONT_FILE: u64 = 256 * 1024 * 1024;
/// The parts of a font file the scan reads: headers, table directories and `name` tables, at their
/// offsets in a zeroed buffer of the file's length (reading whole files was most of the scan).
fn index_bytes(path: &std::path::Path, len: usize) -> Option<Vec<u8>> {