guile-devel
[Top][All Lists]
Advanced

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

Re: segfault in SRFI-1 partition on non-list input


From: Ludovic Courtès
Subject: Re: segfault in SRFI-1 partition on non-list input
Date: Mon, 28 Apr 2008 10:27:54 +0200
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1 (gnu/linux)

Hi Julian,

"Julian Graham" <address@hidden> writes:

> It looks like scm_srfi1_partition in srfi/srfi-1.c fails to verify
> that it's being called on a real list, and so expressions like:
>
> (partition symbol? '(a b . c))
>
> cause Guile to segfault.  Attached is a patch against HEAD that adds 
> validation.

> +  SCM_VALIDATE_LIST (2, list);

The probably is that `SCM_VALIDATE_LIST' uses `scm_ilength ()', which
attempts to traverse the list it's given.  Thus, it is undesirable to
use it here (and in many other places actually).

Instead, I propose the following patch, which doesn't add any list
traversal but doesn't catch circular lists.  What do you think?

Thanks,
Ludovic.

diff --git a/srfi/srfi-1.c b/srfi/srfi-1.c
index 2989a25..0ce834a 100644
--- a/srfi/srfi-1.c
+++ b/srfi/srfi-1.c
@@ -1667,6 +1667,7 @@ SCM_DEFINE (scm_srfi1_partition, "partition", 2, 0, 0,
   /* In this implementation, the output lists don't share memory with
      list, because it's probably not worth the effort. */
   scm_t_trampoline_1 call = scm_trampoline_1(pred);
+  SCM orig_list = list;
   SCM kept = scm_cons(SCM_EOL, SCM_EOL);
   SCM kept_tail = kept;
   SCM dropped = scm_cons(SCM_EOL, SCM_EOL);
@@ -1675,8 +1676,15 @@ SCM_DEFINE (scm_srfi1_partition, "partition", 2, 0, 0,
   SCM_ASSERT(call, pred, 2, FUNC_NAME);
   
   for (; !SCM_NULL_OR_NIL_P (list); list = SCM_CDR(list)) {
-    SCM elt = SCM_CAR(list);
-    SCM new_tail = scm_cons(SCM_CAR(list), SCM_EOL);
+    SCM elt, new_tail;
+
+    /* LIST must be a proper list.
+       XXX: This does not ensure that LIST is not a circular list.  */
+    SCM_ASSERT (scm_is_pair (list), orig_list, 2, FUNC_NAME);
+
+    elt = SCM_CAR (list);
+    new_tail = scm_cons (SCM_CAR (list), SCM_EOL);
+
     if (scm_is_true (call (pred, elt))) {
       SCM_SETCDR(kept_tail, new_tail);
       kept_tail = new_tail;
diff --git a/test-suite/tests/srfi-1.test b/test-suite/tests/srfi-1.test
index 22c4a9a..8fe8097 100644
--- a/test-suite/tests/srfi-1.test
+++ b/test-suite/tests/srfi-1.test
@@ -1,6 +1,6 @@
 ;;;; srfi-1.test --- Test suite for Guile's SRFI-1 functions. -*- scheme -*-
 ;;;;
-;;;; Copyright 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+;;;; Copyright 2003, 2004, 2005, 2006, 2008 Free Software Foundation, Inc.
 ;;;;
 ;;;; This program is free software; you can redistribute it and/or modify
 ;;;; it under the terms of the GNU General Public License as published by
@@ -2068,7 +2068,11 @@
                                   (make-list 10000 1)))
       (lambda (even odd)
        (and (= (length odd) 10000)
-            (= (length even) 0))))))
+            (= (length even) 0)))))
+
+  (pass-if-exception "with improper list"
+    exception:wrong-type-arg
+    (partition symbol? '(a b . c))))
 
 ;;
 ;; partition!

reply via email to

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