star-cad

Geometric operators for computer-aided design
git clone git://git.meso-star.fr/star-cad.git
Log | Files | Refs | README | LICENSE

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:
Msrc/scad.c | 9+++++++--
Msrc/scad.h | 21++++++++++++---------
Msrc/scad_device.c | 23+++++++++++------------
Msrc/scad_geometry.c | 93++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
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;