commit 56c6585df2eb2c628f7870e5c6e7b007c04d9d1e
parent b57c6dc7aa5a0258a7939768e27e71003b1da407
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Tue, 29 Jul 2025 15:50:32 +0200
Improve code robustness
Add missing arg validity tests.
Fix some invalid pointer access.
Remove useless code.
Improve comments.
Diffstat:
4 files changed, 87 insertions(+), 59 deletions(-)
diff --git a/src/scad.c b/src/scad.c
@@ -309,13 +309,15 @@ scad_get_dimtag_refcount
(const int dim,
const int tag)
{
- struct tag_desc* desc = device_get_description(dim, tag);
+ struct tag_desc* desc = NULL;
+
+ if(check_device(FUNC_NAME) != RES_OK) return SIZE_MAX;
+ desc = device_get_description(dim, tag);
if(!desc) return SIZE_MAX;
return desc->refcount;
}
-
res_T
scad_scene_write
(const char* name)
@@ -328,6 +330,7 @@ scad_scene_write
goto error;
}
+ ERR(check_device(FUNC_NAME));
gmshWrite(name, &ierr);
ERR(gmsh_err_to_res_T(ierr));
@@ -751,6 +754,8 @@ scad_stl_data_write
goto error;
}
+ ERR(check_device(FUNC_NAME));
+
coord_n = darray_double_size_get(triangles);
if(coord_n % 9) {
res = RES_BAD_ARG;
diff --git a/src/scad.h b/src/scad.h
@@ -207,7 +207,9 @@ scad_scene_clear
/* Write the whole scene in a format that depends on filename extension.
* Available formats include "brep", "msh" (gmsh-specific format), "step",
- * "stl", "vtk", etc. */
+ * "stl", "vtk", etc.
+ * Note that due to gmsh behaviour, writing a scene that never contained any
+ * geometry ends in error. */
SCAD_API res_T
scad_scene_write
(const char* filename);
@@ -326,12 +328,12 @@ scad_geometry_explode
struct scad_geometry*** out_geometries,
size_t* out_count);
-/* Ref counting of geometries: get a new reference to goemetry `geometry'. */
+/* Ref counting of geometries: get a new reference to geometry `geometry'. */
SCAD_API res_T
scad_geometry_ref_get
(struct scad_geometry* geometry);
-/* Ref counting of geometries: release a reference to goemetry `geometry'. */
+/* Ref counting of geometries: release a reference to geometry `geometry'. */
SCAD_API res_T
scad_geometry_ref_put
(struct scad_geometry* geometry);
@@ -406,7 +408,7 @@ scad_geometry_get_centerofmass
/* Get the `closest' point on geometry `geometry' from point `from'.
* Return the `closest' point and its `distance'.
* The underlying 2D geometry on wich the closest point is located is returned
- * as a new geometry in `closest_geom' if it is not NULL.
+ * as a new geometry in `underlying_geometry' if it is not NULL.
* If `geometry' is 3D, this underlying geometry is (a part of) its boundary. */
SCAD_API res_T
scad_geometry_get_closest_point
@@ -414,7 +416,7 @@ scad_geometry_get_closest_point
const double from[3],
double closest[3],
double* distance,
- struct scad_geometry** closest_geom); /* Can be NULL */
+ struct scad_geometry** underlying_geometry); /* Can be NULL */
/* Get the normal of the geometry `geometry' at position `p'.
* The normal is set in `N' and the underlying 2D geometry on which `p' is
@@ -462,7 +464,6 @@ scad_geometry_is_included
const size_t geometries_count,
int* included);
-
/* Create a new geometry `out_geometry' sharing all the content of geometries in
* `geometries'.
* Note that, while copied geometries (scad_geometry_copy) are not equal as
@@ -485,7 +486,8 @@ scad_geometries_fuse
struct scad_geometry** out_geometry);
/* Compute the boolean difference between the geometries in `geometries' and
- * `tools'. */
+ * `tools'.
+ * Note that the resulting geometry can be empty. */
SCAD_API res_T
scad_geometries_cut
(struct scad_geometry** geometries,
@@ -495,7 +497,8 @@ scad_geometries_cut
struct scad_geometry** out_geometry);
/* Compute the boolean intersection (the common parts) of the geometries
- * in `geometries' and `tools'. */
+ * in `geometries' and `tools'.
+ * Note that the resulting geometry can be empty. */
SCAD_API res_T
scad_geometries_intersect
(struct scad_geometry** geometries,
@@ -750,7 +753,7 @@ scad_dump_geometry
* To use it from gdb:
* (gdb) call scad_dump_geometries()
*/
-SCAD_API void
+SCAD_API res_T
scad_dump_geometries
(void);
diff --git a/src/scad_device.c b/src/scad_device.c
@@ -274,11 +274,6 @@ scad_dump_geometry
}
ERR(check_device(FUNC_NAME));
- if(htable_geometries_is_empty(&dev->allgeom)) {
- printf("No geometry defined.\n");
- return res;
- }
-
if(str_is_empty(&geom->name)) {
printf("Unnamed geometry %p (count is %lu), tags: ",
(void*)geom, (long unsigned)geom->ref);
@@ -299,28 +294,32 @@ error:
goto exit;
}
-void
+res_T
scad_dump_geometries
(void)
{
+ res_T res = RES_OK;
struct scad_device* dev = get_device();
struct htable_geometries_iterator it, end;
- if(!dev) {
- printf("Error: star-cad is not initialized.\n");
- return;
- }
+ ERR(check_device(FUNC_NAME));
+
if(htable_geometries_is_empty(&dev->allgeom)) {
printf("No geometry defined.\n");
- return;
+ goto exit; /* Not an error */
}
htable_geometries_begin(&dev->allgeom, &it);
htable_geometries_end(&dev->allgeom, &end);
while(!htable_geometries_iterator_eq(&it, &end)) {
struct scad_geometry* geom = *htable_geometries_iterator_key_get(&it);
- SCAD(dump_geometry(geom));
+ ERR(scad_dump_geometry(geom));
htable_geometries_iterator_next(&it);
}
+
+exit:
+ return res;
+error:
+ goto exit;
}
static void
diff --git a/src/scad_geometry.c b/src/scad_geometry.c
@@ -404,7 +404,7 @@ geometry_release(ref_T* ref)
geom = CONTAINER_OF(ref, struct scad_geometry, ref);
CHK(RES_OK == device_unregister_tags(dev->log, dev->log_type, geom));
MEM_RM(allocator, geom->gmsh_dimTags);
- if(str_len(&geom->name) != 0) {
+ if(!str_is_empty(&geom->name)) {
n = htable_names_erase(&dev->geometry_names, &geom->name);
ASSERT(n == 1);
}
@@ -751,8 +751,12 @@ scad_geometry_get_mass
size_t i;
int* data = NULL;
size_t sz = 0;
+ double m = 0;
- if(!geom || !mass) goto error;
+ if(!geom || !mass) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
ERR(check_device(FUNC_NAME));
@@ -760,16 +764,16 @@ scad_geometry_get_mass
sz = geom->gmsh_dimTags_n;
ref_dim = data[0];
- *mass = 0;
for(i = 0; i < sz; i += 2) {
- double geom_mass = 0;
+ double geom_mass;
int dim = data[i], tag = data[i+1];
int ierr = 0;
if(ref_dim != dim) goto error;
gmshModelOccGetMass(dim, tag, &geom_mass, &ierr);
ERR(gmsh_err_to_res_T(ierr));
- *mass += geom_mass;
+ m += geom_mass;
}
+ *mass = m;
exit:
return res;
@@ -795,8 +799,9 @@ scad_geometry_get_closest_point
const int* data = NULL;
size_t sz = 0;
int initialized = 0, min_tag = -1;
+ struct scad_geometry* out = NULL;
- if(!geom || !from || !closest) {
+ if(!geom || !from || !closest || !closest_distance) {
res = RES_BAD_ARG;
goto error;
}
@@ -809,7 +814,6 @@ scad_geometry_get_closest_point
ERR(get_2d_tags(geom, &tags));
data = darray_int_cdata_get(&tags);
sz = darray_int_size_get(&tags);
- ASSERT(sz);
for(i = 0; i < sz; i++) {
double d;
@@ -838,25 +842,30 @@ scad_geometry_get_closest_point
d3_set(closest, min);
*closest_distance = min_d;
if(out_geometry) {
- ERR(geometry_create(out_geometry));
- (*out_geometry)->gmsh_dimTags =
- MEM_ALLOC(dev->allocator, 2 * sizeof(*(*out_geometry)->gmsh_dimTags));
- if(!(*out_geometry)->gmsh_dimTags) {
+ ERR(geometry_create(&out));
+ out->gmsh_dimTags =
+ MEM_ALLOC(dev->allocator, 2 * sizeof(*out->gmsh_dimTags));
+ if(!out->gmsh_dimTags) {
res = RES_MEM_ERR;
goto error;
}
- (*out_geometry)->gmsh_dimTags_n = 2;
- (*out_geometry)->gmsh_dimTags[0] = 2;
- (*out_geometry)->gmsh_dimTags[1] = min_tag;
- ERR(device_register_tags(*out_geometry));
+ out->gmsh_dimTags_n = 2;
+ out->gmsh_dimTags[0] = 2;
+ out->gmsh_dimTags[1] = min_tag;
+ ERR(device_register_tags(out));
}
exit:
if(initialized) darray_int_release(&tags);
+ if(out_geometry) *out_geometry = out;
gmshFree(coord);
gmshFree(pcoord);
return res;
error:
+ if(out) {
+ SCAD(geometry_ref_put(out));
+ out = NULL;
+ }
goto exit;
}
@@ -1351,7 +1360,7 @@ scad_geometry_is_included
int initialized = 0;
size_t i, n;
- if(!geometry || !geometries || !included) {
+ if(!geometry || !geometries || geometries_count == 0 || !included) {
res = RES_BAD_ARG;
goto error;
}
@@ -1623,9 +1632,7 @@ scad_geometries_intersect
ERR(geometry_create(&geom));
geom->gmsh_dimTags_n = tagoutn;
- if (tagoutn == 0){
- geom->gmsh_dimTags = NULL;
- } else {
+ if(tagoutn != 0){
geom->gmsh_dimTags = MEM_ALLOC(allocator, tagoutn * sizeof(*tagout));
if(!geom->gmsh_dimTags) {
res = RES_MEM_ERR;
@@ -1679,8 +1686,8 @@ scad_geometries_common_boundaries
struct scad_geometry** out_geom = NULL;
struct mem_allocator* allocator = NULL;
struct scad_device* dev = get_device();
- int log = (dev->options.Misc.LogRefCounting & SCAD_LOG_DIMTAGS_ALL);
- enum log_type log_type = dev->log_type;
+ int log;
+ enum log_type log_type;
size_t i, c = 0, n;
struct str msg, name;
int msg_initialized = 0, name_initialized = 0;
@@ -1726,6 +1733,8 @@ scad_geometries_common_boundaries
name_initialized = 1;
}
+ log = (dev->options.Misc.LogRefCounting & SCAD_LOG_DIMTAGS_ALL);
+ log_type = dev->log_type;
if(log) {
str_init(allocator, &msg);
msg_initialized = 1;
@@ -1868,8 +1877,8 @@ scad_geometry_extrude
int ierr = 0;
struct scad_geometry* extrude_geom = NULL;
struct scad_device* dev = get_device();
- int log = (dev->options.Misc.LogRefCounting & SCAD_LOG_DIMTAGS_ALL);
- enum log_type log_type = dev->log_type;
+ int log;
+ enum log_type log_type;
struct mem_allocator* allocator = NULL;
struct str msg;
int init = 0;
@@ -1920,6 +1929,8 @@ scad_geometry_extrude
ERR(device_register_tags(extrude_geom));
+ log = (dev->options.Misc.LogRefCounting & SCAD_LOG_DIMTAGS_ALL);
+ log_type = dev->log_type;
if(log) {
str_init(allocator, &msg);
init = 1;
@@ -2463,11 +2474,12 @@ scad_geometries_swap
struct mem_allocator* allocator = NULL;
struct str tmp, msg;
- if(!pool1 || !pool2) {
+ if(!pool1 || !pool2 || !flags || count == 0) {
res = RES_BAD_ARG;
goto error;
}
+ ERR(check_device(FUNC_NAME));
allocator = dev->allocator;
if(flags & SCAD_SWAP_NAME) str_init(allocator, &tmp);
if(flags & SCAD_SWAP_GEOMETRY && dev->log) str_init(allocator, &msg);
@@ -2600,8 +2612,8 @@ scad_geometries_boundary
struct scad_geometry** out_geom = NULL;
struct mem_allocator* allocator = NULL;
struct scad_device* dev = get_device();
- int log = (dev->options.Misc.LogRefCounting & SCAD_LOG_DIMTAGS_ALL);
- enum log_type log_type = dev->log_type;
+ int log;
+ enum log_type log_type;
size_t i, c = 0, n;
struct str msg, name;
int msg_initialized = 0, name_initialized = 0;
@@ -2631,6 +2643,8 @@ scad_geometries_boundary
name_initialized = 1;
}
+ log = (dev->options.Misc.LogRefCounting & SCAD_LOG_DIMTAGS_ALL);
+ log_type = dev->log_type;
if(log) {
str_init(allocator, &msg);
msg_initialized = 1;
@@ -2985,8 +2999,10 @@ scad_geometries_set_mesh_size_modifier
ERR(gmsh_err_to_res_T(ierr));
exit:
- for(dim = 0; dim < 4; dim++) {
- MEM_RM(dev->allocator, tagout[dim]);
+ if(dev) {
+ for(dim = 0; dim < 4; dim++) {
+ MEM_RM(dev->allocator, tagout[dim]);
+ }
}
return res;
error:
@@ -3021,8 +3037,10 @@ scad_geometries_set_mesh_algorithm
}
exit:
- for(i = 2; i < 4; i++) {
- MEM_RM(dev->allocator, tagout[i]);
+ if(dev) {
+ for(i = 2; i < 4; i++) {
+ MEM_RM(dev->allocator, tagout[i]);
+ }
}
return res;
error:
@@ -3039,7 +3057,7 @@ scad_geometries_set_periodic
{
res_T res = RES_OK;
struct scad_device* dev = get_device();
- struct mem_allocator* allocator = dev->allocator;
+ struct mem_allocator* allocator = NULL;
int ierr;
int* src_dimTagout[4] = { NULL, NULL, NULL, NULL };
int* tgt_dimTagout[4] = { NULL, NULL, NULL, NULL };
@@ -3063,6 +3081,7 @@ scad_geometries_set_periodic
goto error;
}
+ allocator = dev->allocator;
src_tags = MEM_ALLOC(allocator, src_tagsn);
tgt_tags = MEM_ALLOC(allocator, tgt_tagsn);
if(!src_tags || !tgt_tags) {
@@ -3080,12 +3099,14 @@ scad_geometries_set_periodic
ERR(gmsh_err_to_res_T(ierr));
exit:
- for(i = 2; i < 4; i++) {
- MEM_RM(dev->allocator, src_dimTagout[i]);
- MEM_RM(dev->allocator, tgt_dimTagout[i]);
+ if(dev) {
+ for(i = 2; i < 4; i++) {
+ MEM_RM(dev->allocator, src_dimTagout[i]);
+ MEM_RM(dev->allocator, tgt_dimTagout[i]);
+ }
+ MEM_RM(dev->allocator, src_tags);
+ MEM_RM(dev->allocator, tgt_tags);
}
- MEM_RM(dev->allocator, src_tags);
- MEM_RM(dev->allocator, tgt_tags);
return res;
error:
goto exit;