bug-guile
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: stack overflow equal? values


From: Ludovic Courtès
Subject: Re: stack overflow equal? values
Date: Thu, 18 Jan 2007 13:57:50 +0100
User-agent: Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux)

Hi Kevin,

Kevin Ryde <address@hidden> writes:

> "Marco Maggi" <address@hidden> writes:
>>
>> guile> (equal? (values 1 2) (values 1 2))
>> ERROR: Stack overflow
>
> Thanks, looks like a bug introduced by recursing into structs in
> equal?.  I guess scm_i_struct_equalp should check and ignore a field
> type "s" ...

Indeed, good guess!

I propose the following simple fix.  Ok to apply?

Actually, `scm_i_struct_equalp ()' should also compare the "tail
elements" (when there are tail elements), but their semantics are a
little fuzzy to me.  In particular, I don't understand why the size of
the tail array can be specified in both `make-vtable-vtable' and
`make-struct': What does that mean?  Which one should really be taken
into account?  It seems that the code is a bit unclear on this too:

  guile> (define v (make-vtable-vtable "pr" 0))
  guile> (define s (make-struct v 123))
  guile> (struct-ref s 10)
  Segmentation fault

(Looks like the API is so complex that few people actually bothered to
use it to its full extents.  ;-))

Thanks,
Ludovic.


--- orig/libguile/struct.c
+++ mod/libguile/struct.c
@@ -564,8 +564,11 @@
       field1 = scm_struct_ref (s1, s_field_num);
       field2 = scm_struct_ref (s2, s_field_num);
 
-      if (scm_is_false (scm_equal_p (field1, field2)))
-       return SCM_BOOL_F;
+      /* Self-referencing fields (type `s') must be skipped to avoid infinite
+        recursion.  */
+      if (!(scm_is_eq (field1, s1) && (scm_is_eq (field2, s2))))
+       if (scm_is_false (scm_equal_p (field1, field2)))
+         return SCM_BOOL_F;
     }
 
   return SCM_BOOL_T;


--- orig/test-suite/tests/structs.test
+++ mod/test-suite/tests/structs.test
@@ -82,12 +82,18 @@
        (set-owner! ball "Bill")
        (string=? (owner ball) "Bill")))
 
-  (pass-if "equal?"
+  (pass-if "equal? (simple structs)"
+     (let* ((vtable (make-vtable-vtable "pr" 0))
+            (s1     (make-struct vtable 0 "hello"))
+            (s2     (make-struct vtable 0 "hello")))
+       (equal? s1 s2)))
+
+  (pass-if "equal? (more complex structs)"
      (let ((first (make-ball red (string-copy "Bob")))
-          (second (make-ball red (string-copy "Bob"))))
+           (second (make-ball red (string-copy "Bob"))))
        (equal? first second)))
 
   (pass-if "not-equal?"
-     (not (or (equal? (make-ball red "Bob") (make-ball green "Bill"))
+     (not (or (equal? (make-ball red "Bob") (make-ball green "Bob"))
              (equal? (make-ball red "Bob") (make-ball red "Bill"))))))
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]