Kyle/Martin,
What is the status of this? I'd like to have a 21.1.10 patch, if
possible.
- vin
>>>>> On Fri, 17 Dec 1999, Martin Buchholz <martin(a)xemacs.org> said:
>>>>> "Kyle" == Kyle Jones <kyle_jones(a)wonderworks.com> writes:
Kyle> Jan Vroonhof writes:
>>> Here is an easier one
>>>
>>> (let ((lijst '(a b c)))
>>> (mapcar
>>> (lambda (x)
>>> ;; Make list shorter behind mapcar's back
>>> (delete 'c lijst))
>>> lijst))
>>>
>>> The problem is this code in in mapcar1
>>>
>>> if (LISTP (seq))
>>> {
>>> for (i = 0; i < leni; i++)
>>> {
>>> args[1] = XCAR (seq);
>>> seq = XCDR (seq);
>>> result = Ffuncall (2, args);
>>> if (vals) vals[gcpro1.nvars++] = result;
>>> }
>>> }
>>>
>>> It blindingly believes that XCDR(seq) will always be a cons cell,
>>> although it calls user code which could have modified the list it is
>>> iterating over.
Kyle> Here's a patch that fixes this. Recommended for 21.1 and 21.2.
Martin> There's another GC bug with this code I tried to fix. If you are
Martin> iterating over the list, and the mapping function destructively
Martin> modifies the list by breaking it in the middle using (setcdr), the
Martin> remaining list will not have any references and can be garbage
Martin> collected.
Martin> If you evaluate this in a debug xemacs, it will crash.
Martin> (let ((x (list (cons 1 1) (cons 2 2) (cons 3 3) (cons 4 4))))
Martin> (mapcar (lambda (y)
Martin> (garbage-collect)
Martin> (when (eq (car y) 2)
Martin> (setcdr x nil)
Martin> (garbage-collect))
Martin> (print (car y)))
Martin> x))
Martin> However, my own patch needs more work as well, I think. Perhaps I
Martin> should separate out the dostring fiddling from the pure bug fix, eh?
Martin> So, for the time being I veto both of our patches. I want to finish
Martin> this work since I feel vaguely responsible for the core lisp stuff.
Kyle> 1999-12-16 Kyle Jones <kyle_jones(a)wonderworks.com>
Kyle> * fns.c (mapcar1): when iterating over a list, check for
Kyle> CONSP each iteration because bad user code might have
Kyle> modified the list. Call Fcdr/Fcar if CONSP check fails
Kyle> so that malformed lists cause an error to be signaled
Kyle> instead of crashing.
Kyle> --- src/fns.c 1999/10/24 03:48:39 1.30.2.23
Kyle> +++ src/fns.c 1999/12/17 04:13:14
Kyle> @@ -3070,8 +3070,19 @@
Kyle> {
Kyle> for (i = 0; i < leni; i++)
Kyle> {
Kyle> - args[1] = XCAR (seq);
Kyle> - seq = XCDR (seq);
Kyle> + /* Use XCAR/XCDR to avoid function call overhead if we can.
Kyle> + Otherwise call Fcar and Fcdr to get exceptions signaled
Kyle> + if the Lisp code mangles the list. */
Kyle> + if (CONSP (seq))
Kyle> + {
Kyle> + args[1] = XCAR (seq);
Kyle> + seq = XCDR (seq);
Kyle> + }
Kyle> + else
Kyle> + {
Kyle> + args[1] = Fcar (seq);
Kyle> + seq = Fcdr (seq);
Kyle> + }
Kyle> result = Ffuncall (2, args);
Kyle> if (vals) vals[gcpro1.nvars++] = result;
Kyle> }