Bound typed counts and values that could crash the editor

- ARRAYRECT, ARRAYPOLAR, ARRAYPATH, ARRAY3D and COPY Array reject item
  counts above 100,000 (checked as a product of every dimension) and keep
  the prompt open. Unbounded counts allocated one transform per item and
  aborted on allocation failure. Stored defaults are clamped as well.
- EXPLODE leaves a MINSERT above the same limit intact instead of
  materializing every cell.
- Typed lengths and angles reject non-finite values and magnitudes above
  1e15; SCALE rejects a non-finite factor.
- Zero-radius FILLET compares candidate intersections with total_cmp and
  rejects non-finite results; partial_cmp().unwrap() panicked on NaN.
- SOLID falls back to a minimal kernel tolerance when its corners' extent
  overflows, since Tolerance::new panics on infinity.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Christopher OverbeckandClaude Opus 5 committed 2026-09-17 10:33:18 -05:00
1 parent 38aa2ee34d
commit a3d65e2fc8
7 files changed
+223 -15

No files matched your search

+28 -3
View File
@@ -1062,10 +1062,13 @@ fn fillet_line_arc(
+ (p1[1] + a * u[1] - click_line[1]).powi(2);
let db = (p1[0] + b * u[0] - click_line[0]).powi(2)
+ (p1[1] + b * u[1] - click_line[1]).powi(2);
da.partial_cmp(&db).unwrap()
da.total_cmp(&db)
})?;
let ix = p1[0] + t_best * u[0];
let iy = p1[1] + t_best * u[1];
if !(ix.is_finite() && iy.is_finite()) {
return None;
}
// Trim line to intersection
let new_line = trim_line_to_point(line, [ix, iy], click_line)?;
@@ -1154,9 +1157,11 @@ fn fillet_arc_arc(
let ip = *pts.iter().min_by(|a, b| {
(a[0] - cx)
.hypot(a[1] - cy)
.partial_cmp(&(b[0] - cx).hypot(b[1] - cy))
.unwrap()
.total_cmp(&(b[0] - cx).hypot(b[1] - cy))
})?;
if !(ip[0].is_finite() && ip[1].is_finite()) {
return None;
}
let ia1 = arc_angle_at(c1, ip);
let ia2 = arc_angle_at(c2, ip);
@@ -2368,6 +2373,26 @@ mod tests {
cmd.options().into_iter().map(|o| o.keyword).collect()
}
/// The upper half of a radius-5 circle at (5, 0), scaled about the origin
/// by an infinite factor: the center becomes (inf, NaN).
fn overflowed_arc(sweep_sign: f64) -> ArcEnt {
let mut arc = ArcEnt::new();
arc.center = acadrust::types::Vector3::new(f64::INFINITY, f64::NAN, 0.0);
arc.radius = f64::INFINITY;
arc.start_angle = 0.0;
arc.end_angle = sweep_sign * std::f64::consts::PI;
arc
}
#[test]
fn zero_radius_fillet_rejects_non_finite_geometry() {
let line = LineEnt::from_coords(f64::NAN, f64::NAN, 0.0, f64::INFINITY, f64::INFINITY, 0.0);
let arc = overflowed_arc(1.0);
assert!(fillet_line_arc(&line, [5.0, 5.0], &arc, [5.0, 5.0], 0.0, 0.0).is_none());
let other = overflowed_arc(-1.0);
assert!(fillet_arc_arc(&arc, [5.0, 5.0], &other, [5.0, -5.0], 0.0, 0.0).is_none());
}
#[test]
fn fillet_undo_option_appears_after_a_fillet_and_refreshes_from_document() {
let mut command = FilletCommand::new(