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.
Here's a patch that fixes this. Recommended for 21.1 and 21.2.
1999-12-16 Kyle Jones <kyle_jones(a)wonderworks.com>
* fns.c (mapcar1): when iterating over a list, check for
CONSP each iteration because bad user code might have
modified the list. Call Fcdr/Fcar if CONSP check fails
so that malformed lists cause an error to be signaled
instead of crashing.
--- src/fns.c 1999/10/24 03:48:39 1.30.2.23
+++ src/fns.c 1999/12/17 04:13:14
@@ -3070,8 +3070,19 @@
{
for (i = 0; i < leni; i++)
{
- args[1] = XCAR (seq);
- seq = XCDR (seq);
+ /* Use XCAR/XCDR to avoid function call overhead if we can.
+ Otherwise call Fcar and Fcdr to get exceptions signaled
+ if the Lisp code mangles the list. */
+ if (CONSP (seq))
+ {
+ args[1] = XCAR (seq);
+ seq = XCDR (seq);
+ }
+ else
+ {
+ args[1] = Fcar (seq);
+ seq = Fcdr (seq);
+ }
result = Ffuncall (2, args);
if (vals) vals[gcpro1.nvars++] = result;
}