mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-24 09:57:08 -06:00
security(affinity): index live-corner radii by record
subpath() looked up each polyline anchor's corner radius by scanning the entire radius list, O(anchors * radii). A file supplying large anchor and radius arrays could cause quadratic CPU work before geometry limits inspected the path. Build a record-to-maximum-radius map once and look each anchor up in it, preserving the previous fold(0.0, f64::max) behavior for duplicate record indices. Finding: 89f65d65-f637-44fc-9a81-a9039a413a4b (CWE-407)
This commit is contained in:
@@ -210,7 +210,16 @@ fn anchors(records: &[Value]) -> Option<Vec<Anchor>> {
|
||||
fn subpath(anchors: &[Anchor], closed: bool, radii: Option<&Vec<(usize, f64)>>) -> Option<SubPath> {
|
||||
let first = anchors.first()?;
|
||||
if let Some(radii) = radii.filter(|r| !r.is_empty()) {
|
||||
let corner = |a: &Anchor| radii.iter().filter(|(rec, _)| *rec == a.record).map(|(_, r)| *r).fold(0.0, f64::max);
|
||||
// Index each record's maximum radius once. Scanning the whole radius list per anchor
|
||||
// was O(anchors * radii), which a file with large anchor and radius arrays could drive
|
||||
// into quadratic work. Duplicate record indices keep the maximum, matching the prior
|
||||
// fold(0.0, f64::max) behavior.
|
||||
let mut radius_by_record: std::collections::HashMap<usize, f64> = std::collections::HashMap::with_capacity(radii.len());
|
||||
for &(rec, r) in radii {
|
||||
let slot = radius_by_record.entry(rec).or_insert(0.0);
|
||||
*slot = slot.max(r);
|
||||
}
|
||||
let corner = |a: &Anchor| radius_by_record.get(&a.record).copied().unwrap_or(0.0);
|
||||
let polyline = anchors.iter().all(|a| a.inh.is_none_or(|h| h == a.p) && a.out.is_none_or(|h| h == a.p));
|
||||
if polyline {
|
||||
let mut pts: Vec<(Point, f64)> = anchors.iter().map(|a| (a.p, corner(a))).collect();
|
||||
|
||||
Reference in New Issue
Block a user