From 7422c6d5f243f5d2adcb4d3ecddaccdc9d693198 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 20 Aug 2026 12:32:32 +0200 Subject: [PATCH 1/2] Use buffer sizes for pyProject span validation Replaced strict 2D `ndim` checks with stride-based element-count validation in `pyProject`, ensuring each input buffer size is divisible by its struct width (2 or 3). Span lengths are now derived from total element counts (`size / stride`) instead of `shape[0]`, allowing compatible flattened buffers while keeping matrix and camera-normal size checks intact. --- pyUvula/pyUvula.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pyUvula/pyUvula.cpp b/pyUvula/pyUvula.cpp index 632353e..f0e9c5d 100644 --- a/pyUvula/pyUvula.cpp +++ b/pyUvula/pyUvula.cpp @@ -72,9 +72,9 @@ py::list pyProject( const pybind11::buffer_info camera_projection_matrix_buf = camera_projection_matrix_array.request(); const pybind11::buffer_info camera_normal_buf = camera_normal_array.request(); - if (stroke_polygon_buffer.ndim != 2 || mesh_vertices_buffer.ndim != 2 || mesh_indices_buffer.ndim != 2 || mesh_uv_buffer.ndim != 2 || mesh_faces_connectivity_buffer.ndim != 2) + if (stroke_polygon_buffer.size % 2 != 0 || mesh_vertices_buffer.size % 3 != 0 || mesh_indices_buffer.size % 3 != 0 || mesh_uv_buffer.size % 2 != 0 || mesh_faces_connectivity_buffer.size % 3 != 0) { - throw std::runtime_error("Invalid array dimensions for projection inputs (expected 2D arrays)."); + throw std::runtime_error("Invalid buffer sizes for projection inputs (element counts must be divisible by struct stride)."); } if (camera_projection_matrix_buf.size != 16 || camera_normal_buf.size != 3) @@ -82,11 +82,11 @@ py::list pyProject( throw std::runtime_error("Invalid matrix or camera normal buffer size."); } - const std::span stroke_polygon = std::span(static_cast(stroke_polygon_buffer.ptr), stroke_polygon_buffer.shape[0]); - const std::span mesh_vertices = std::span(static_cast(mesh_vertices_buffer.ptr), mesh_vertices_buffer.shape[0]); - const std::span mesh_indices = std::span(static_cast(mesh_indices_buffer.ptr), mesh_indices_buffer.shape[0]); - const std::span mesh_uv = std::span(static_cast(mesh_uv_buffer.ptr), mesh_uv_buffer.shape[0]); - const std::span mesh_faces_connectivity = std::span(static_cast(mesh_faces_connectivity_buffer.ptr), mesh_faces_connectivity_buffer.shape[0]); + const std::span stroke_polygon = std::span(static_cast(stroke_polygon_buffer.ptr), stroke_polygon_buffer.size / 2); + const std::span mesh_vertices = std::span(static_cast(mesh_vertices_buffer.ptr), mesh_vertices_buffer.size / 3); + const std::span mesh_indices = std::span(static_cast(mesh_indices_buffer.ptr), mesh_indices_buffer.size / 3); + const std::span mesh_uv = std::span(static_cast(mesh_uv_buffer.ptr), mesh_uv_buffer.size / 2); + const std::span mesh_faces_connectivity = std::span(static_cast(mesh_faces_connectivity_buffer.ptr), mesh_faces_connectivity_buffer.size / 3); const Matrix44F camera_projection_matrix(*static_cast(camera_projection_matrix_buf.ptr)); From 3538d414bc0363aa3e1abf7e219b5d85b54fe86d Mon Sep 17 00:00:00 2001 From: HellAholic Date: Thu, 20 Aug 2026 12:42:39 +0200 Subject: [PATCH 2/2] Add comment to document the change --- pyUvula/pyUvula.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/pyUvula/pyUvula.cpp b/pyUvula/pyUvula.cpp index f0e9c5d..dd10005 100644 --- a/pyUvula/pyUvula.cpp +++ b/pyUvula/pyUvula.cpp @@ -82,6 +82,7 @@ py::list pyProject( throw std::runtime_error("Invalid matrix or camera normal buffer size."); } + // size/stride gives the correct struct count for both flat 1D and shaped 2D arrays; shape[0] only works for 2D. const std::span stroke_polygon = std::span(static_cast(stroke_polygon_buffer.ptr), stroke_polygon_buffer.size / 2); const std::span mesh_vertices = std::span(static_cast(mesh_vertices_buffer.ptr), mesh_vertices_buffer.size / 3); const std::span mesh_indices = std::span(static_cast(mesh_indices_buffer.ptr), mesh_indices_buffer.size / 3);