forked from 1b-agent/opencadstudio-upstream
fix(io): drop more parser-garbage entities to prevent OOM on open
Adds vertex-coordinate, thickness, and dimension-validity checks to `is_entity_corrupt`. Sample files with degenerate Arcs (radius ~5e-14 and zero sweep) or 100k-vertex LwPolylines at coords ~1e244 used to pass the previous check, then crash inside truck's parameter_division with a 3 GB allocation. Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
aea113e687
commit
ace99541d0
1 file changed
+46
-5
+46
-5
@@ -258,35 +258,76 @@ fn finite_vec3(v: &acadrust::types::Vector3) -> bool {
|
|||||||
/// Returns true if the entity looks like parser garbage and should be dropped.
|
/// Returns true if the entity looks like parser garbage and should be dropped.
|
||||||
fn is_entity_corrupt(e: &EntityType) -> bool {
|
fn is_entity_corrupt(e: &EntityType) -> bool {
|
||||||
use acadrust::entities::EntityType as E;
|
use acadrust::entities::EntityType as E;
|
||||||
|
// Reject polylines at or above this vertex count. Even valid drawings
|
||||||
|
// rarely use this many — and parser desync produces exactly-100_000-vertex
|
||||||
|
// junk records.
|
||||||
const MAX_VERTS: usize = 100_000;
|
const MAX_VERTS: usize = 100_000;
|
||||||
match e {
|
match e {
|
||||||
E::LwPolyline(p) => {
|
E::LwPolyline(p) => {
|
||||||
!finite_unit_normal(&p.normal)
|
!finite_unit_normal(&p.normal)
|
||||||
|| p.vertices.len() > MAX_VERTS
|
|| p.vertices.len() >= MAX_VERTS
|
||||||
|| !finite_coord(p.elevation)
|
|| !finite_coord(p.elevation)
|
||||||
|| p.elevation.abs() > 1.0e10
|
|| p.elevation.abs() > 1.0e10
|
||||||
|
|| !finite_coord(p.thickness)
|
||||||
|
|| p.thickness.abs() > 1.0e10
|
||||||
|
|| p.vertices
|
||||||
|
.iter()
|
||||||
|
.any(|v| !finite_coord(v.location.x) || !finite_coord(v.location.y))
|
||||||
}
|
}
|
||||||
E::Polyline2D(p) => {
|
E::Polyline2D(p) => {
|
||||||
!finite_unit_normal(&p.normal)
|
!finite_unit_normal(&p.normal)
|
||||||
|| p.vertices.len() > MAX_VERTS
|
|| p.vertices.len() >= MAX_VERTS
|
||||||
|| !finite_coord(p.elevation)
|
|| !finite_coord(p.elevation)
|
||||||
|| p.elevation.abs() > 1.0e10
|
|| p.elevation.abs() > 1.0e10
|
||||||
|
|| !finite_coord(p.thickness)
|
||||||
|
|| p.thickness.abs() > 1.0e10
|
||||||
|
|| p.vertices.iter().any(|v| !finite_vec3(&v.location))
|
||||||
}
|
}
|
||||||
E::Polyline3D(p) => {
|
E::Polyline3D(p) => {
|
||||||
p.vertices.len() > MAX_VERTS
|
p.vertices.len() >= MAX_VERTS
|
||||||
|| p.vertices.iter().any(|v| !finite_vec3(&v.position))
|
|| p.vertices.iter().any(|v| !finite_vec3(&v.position))
|
||||||
}
|
}
|
||||||
E::Polyline(p) => {
|
E::Polyline(p) => {
|
||||||
p.vertices.len() > MAX_VERTS
|
p.vertices.len() >= MAX_VERTS
|
||||||
|| p.vertices.iter().any(|v| !finite_vec3(&v.location))
|
|| p.vertices.iter().any(|v| !finite_vec3(&v.location))
|
||||||
}
|
}
|
||||||
E::Line(l) => !finite_vec3(&l.start) || !finite_vec3(&l.end),
|
E::Line(l) => !finite_vec3(&l.start) || !finite_vec3(&l.end),
|
||||||
E::Circle(c) => !finite_vec3(&c.center) || !finite_coord(c.radius),
|
E::Circle(c) => {
|
||||||
|
!finite_vec3(&c.center)
|
||||||
|
|| !finite_coord(c.radius)
|
||||||
|
// Reject zero- or near-zero circles: they tessellate into a
|
||||||
|
// degenerate truck curve that crashes parameter_division.
|
||||||
|
|| c.radius.abs() < 1.0e-10
|
||||||
|
|| c.radius.abs() > 1.0e10
|
||||||
|
}
|
||||||
E::Arc(a) => {
|
E::Arc(a) => {
|
||||||
!finite_vec3(&a.center)
|
!finite_vec3(&a.center)
|
||||||
|| !finite_coord(a.radius)
|
|| !finite_coord(a.radius)
|
||||||
|| !a.start_angle.is_finite()
|
|| !a.start_angle.is_finite()
|
||||||
|| !a.end_angle.is_finite()
|
|| !a.end_angle.is_finite()
|
||||||
|
// Same degenerate-curve guard as Circle.
|
||||||
|
|| a.radius.abs() < 1.0e-10
|
||||||
|
|| a.radius.abs() > 1.0e10
|
||||||
|
// Zero-sweep arc (start_angle == end_angle, modulo 2π) collapses
|
||||||
|
// to a single point in WCS — truck's circle_arc on three
|
||||||
|
// coincident vertices recurses unboundedly in parameter_division.
|
||||||
|
|| (a.end_angle - a.start_angle).abs() < 1.0e-9
|
||||||
|
|| !finite_unit_normal(&a.normal)
|
||||||
|
}
|
||||||
|
E::Ellipse(e) => {
|
||||||
|
!finite_vec3(&e.center)
|
||||||
|
|| !finite_vec3(&e.major_axis)
|
||||||
|
|| !e.start_parameter.is_finite()
|
||||||
|
|| !e.end_parameter.is_finite()
|
||||||
|
|| (e.end_parameter - e.start_parameter).abs() < 1.0e-9
|
||||||
|
|| {
|
||||||
|
let m2 = e.major_axis.x * e.major_axis.x
|
||||||
|
+ e.major_axis.y * e.major_axis.y
|
||||||
|
+ e.major_axis.z * e.major_axis.z;
|
||||||
|
!m2.is_finite() || m2 < 1.0e-20 || m2 > 1.0e20
|
||||||
|
}
|
||||||
|
|| !e.minor_axis_ratio.is_finite()
|
||||||
|
|| e.minor_axis_ratio.abs() < 1.0e-10
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user