aboutsummaryrefslogtreecommitdiffstats
path: root/generat3d
diff options
context:
space:
mode:
Diffstat (limited to 'generat3d')
-rw-r--r--generat3d/config.py5
-rw-r--r--generat3d/library.py3
-rw-r--r--generat3d/scene.py22
3 files changed, 24 insertions, 6 deletions
diff --git a/generat3d/config.py b/generat3d/config.py
index 804723f..fbb9f4d 100644
--- a/generat3d/config.py
+++ b/generat3d/config.py
@@ -53,7 +53,10 @@ def library_roots(cli_roots, path=None):
for r in roots:
if not r.strip():
raise Error("empty library root")
- p = Path(r).expanduser()
+ try:
+ p = Path(r).expanduser()
+ except RuntimeError:
+ raise Error(f"cannot expand library root: {r}") from None
if not p.is_dir():
raise Error(f"library root not found: {p}")
out.append(p)
diff --git a/generat3d/library.py b/generat3d/library.py
index ea12794..39ad6fb 100644
--- a/generat3d/library.py
+++ b/generat3d/library.py
@@ -18,6 +18,7 @@
import gzip
import json
import os
+import zlib
from pathlib import Path
from urllib.parse import unquote
@@ -41,7 +42,7 @@ def read_dson(path):
if data[:2] == b"\x1f\x8b":
data = gzip.decompress(data)
return json.loads(data)
- except (OSError, EOFError, ValueError) as e:
+ except (OSError, EOFError, ValueError, zlib.error, RecursionError) as e:
raise Error(f"{path}: {e}") from None
diff --git a/generat3d/scene.py b/generat3d/scene.py
index 25e4b61..28dc00c 100644
--- a/generat3d/scene.py
+++ b/generat3d/scene.py
@@ -62,9 +62,17 @@ class Scene:
graph: Graph
+def _finite(v):
+ return (not isinstance(v, bool) and isinstance(v, (int, float))
+ and math.isfinite(v))
+
+
def _channel(node, name):
comps = {c["id"]: c.get("current_value", c.get("value", 0.0)) for c in node.get(name, [])}
- return [comps.get(a, 0.0) for a in AXES]
+ out = [comps.get(a, 0.0) for a in AXES]
+ if not all(_finite(v) for v in out):
+ raise Error(f"{node['id']}: {name} is not a finite number")
+ return out
def _lookup(library, doc, url, section):
@@ -147,9 +155,12 @@ class _Loader:
self.graph.add_prop(key(n["id"], n["id"], f"{ch}/{a}"), v)
for f in n.get("formulas", []):
self.pending.append((f, fpath))
+ verts = np.array(geom["vertices"]["values"], dtype=float)
+ if verts.ndim != 2 or verts.shape[1] != 3 or not np.isfinite(verts).all():
+ raise Error(f"{fpath}: bad vertices")
return Figure(asset["id"], inst.get("name", asset.get("name", asset["id"])),
inst.get("label", asset.get("label", asset["id"])),
- np.array(geom["vertices"]["values"], dtype=float),
+ verts,
list(geom.get("polygon_material_groups", {}).get("values", [])),
nodes)
@@ -179,6 +190,9 @@ class _Loader:
if parent and parent != self.figure.id:
continue
ch = mod.get("channel", {})
+ for name in ("value", "min", "max"):
+ if name in ch and not _finite(ch[name]):
+ raise Error(f"{path}#{mod['id']}: {name} is not a finite number")
k = key(self.figure.id, mod["id"], "value")
self.graph.add_prop(k, ch.get("value", 0.0), ch.get("min", -math.inf),
ch.get("max", math.inf), ch.get("clamped", False))
@@ -206,7 +220,7 @@ class _Loader:
doc = self.library.load(path)
try:
self._modifiers(path, doc)
- except (KeyError, TypeError, ValueError, IndexError, AttributeError) as e:
+ except (KeyError, TypeError, ValueError, IndexError, AttributeError, OverflowError) as e:
raise Error(f"{path}: malformed morph data: {e!r}") from None
def _morphs(self, fpath):
@@ -263,5 +277,5 @@ def load(path, library):
"""Load a .duf scene and everything its figure needs."""
try:
return _Loader(path, library).run()
- except (KeyError, TypeError, IndexError, ValueError, AttributeError) as e:
+ except (KeyError, TypeError, IndexError, ValueError, AttributeError, OverflowError) as e:
raise Error(f"{path}: malformed scene data: {e!r}") from None