mirror of
https://github.com/justinethier/cyclone.git
synced 2025-07-15 08:47:35 +02:00
Issue #143 - Track recursion depth of equalp
This prevents the possibility of segfaulting when traversing arbitrarily complex circular structures.
This commit is contained in:
parent
95a4a49dc7
commit
5101de1547
3 changed files with 14 additions and 8 deletions
|
@ -4,7 +4,7 @@
|
|||
|
||||
Bug Fixes
|
||||
|
||||
- Enforce a maximum recursion depth when printing an object via `display` and `write`. This prevents segmentation faults when printing circular data structures.
|
||||
- Enforce a maximum recursion depth when printing an object via `display` and `write`, and when comparing objects via `equal?`. This prevents segmentation faults when working with circular data structures.
|
||||
|
||||
## 0.34.0 - January 2, 2022
|
||||
|
||||
|
|
|
@ -574,7 +574,6 @@ double MRG32k3a (double seed);
|
|||
//object Cyc_eq(object x, object y);
|
||||
object Cyc_eqv(object x, object y);
|
||||
#define Cyc_eq(x, y) (make_boolean(x == y))
|
||||
int equal(object, object);
|
||||
object equalp(object, object);
|
||||
object Cyc_has_cycle(object lst);
|
||||
object Cyc_is_list(object lst);
|
||||
|
|
19
runtime.c
19
runtime.c
|
@ -785,7 +785,8 @@ void Cyc_rt_raise_msg(void *data, const char *err)
|
|||
|
||||
/* END exception handler */
|
||||
|
||||
int equal(object x, object y)
|
||||
object _equalp(object x, object y, int depth);
|
||||
static int equal(object x, object y, int depth)
|
||||
{
|
||||
if (x == y)
|
||||
return 1;
|
||||
|
@ -818,7 +819,7 @@ int equal(object x, object y)
|
|||
int i;
|
||||
if (x == y) return 1;
|
||||
for (i = 0; i < ((vector) x)->num_elements; i++) {
|
||||
if (equalp(((vector) x)->elements[i], ((vector) y)->elements[i]) ==
|
||||
if (_equalp(((vector) x)->elements[i], ((vector) y)->elements[i], depth + 1) ==
|
||||
boolean_f)
|
||||
return 0;
|
||||
}
|
||||
|
@ -1217,7 +1218,8 @@ done:
|
|||
return quote_void;
|
||||
}
|
||||
|
||||
object Cyc_display(void *data, object x, FILE * port) {
|
||||
object Cyc_display(void *data, object x, FILE * port)
|
||||
{
|
||||
return _Cyc_display(data, x, port, 0);
|
||||
}
|
||||
|
||||
|
@ -1624,7 +1626,7 @@ object Cyc_heap_alloc_port(void *data, port_type *stack_p)
|
|||
/**
|
||||
* Check two objects for deep equality
|
||||
*/
|
||||
object equalp(object x, object y)
|
||||
object _equalp(object x, object y, int depth)
|
||||
{
|
||||
int second_cycle = 0;
|
||||
object slow_lis = x, fast_lis = NULL;
|
||||
|
@ -1636,7 +1638,7 @@ object equalp(object x, object y)
|
|||
}
|
||||
|
||||
for (;; x = cdr(x), y = cdr(y)) {
|
||||
if (equal(x, y))
|
||||
if (depth == MAX_DEPTH || equal(x, y, depth))
|
||||
return boolean_t;
|
||||
if (is_value_type(x) || is_value_type(y) ||
|
||||
(x == NULL) || (y == NULL) ||
|
||||
|
@ -1648,7 +1650,7 @@ object equalp(object x, object y)
|
|||
pcar_y == car(y)) {
|
||||
// do nothing, already equal
|
||||
} else {
|
||||
if (boolean_f == equalp(car(x), car(y)))
|
||||
if (boolean_f == _equalp(car(x), car(y), depth + 1))
|
||||
return boolean_f;
|
||||
pcar_x = car(x);
|
||||
pcar_y = car(y);
|
||||
|
@ -1682,6 +1684,11 @@ object equalp(object x, object y)
|
|||
}
|
||||
}
|
||||
|
||||
object equalp(object x, object y)
|
||||
{
|
||||
return _equalp(x, y, 0);
|
||||
}
|
||||
|
||||
object Cyc_num_cmp_va_list(void *data, int argc,
|
||||
int (fn_op(void *, object, object)), object n,
|
||||
va_list ns)
|
||||
|
|
Loading…
Add table
Reference in a new issue