bug-guile
[Top][All Lists]
Advanced

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

Fix for 1001-local-eval-error-backtrace-segfaults - please review


From: Neil Jerram
Subject: Fix for 1001-local-eval-error-backtrace-segfaults - please review
Date: 02 May 2002 13:59:06 +0100
User-agent: Gnus/5.0808 (Gnus v5.8.8) Emacs/20.7

Patch

--- /home/neil/Guile/1.6/guile-core/libguile/eval.c.old Thu May  2 12:45:56 2002
+++ /home/neil/Guile/1.6/guile-core/libguile/eval.c     Thu May  2 12:46:21 2002
@@ -1417,7 +1417,9 @@
        ls = scm_cons (scm_sym_define,
                       z = scm_cons (n = SCM_CAR (x), SCM_UNSPECIFIED));
        if (SCM_NNULLP (env))
-         SCM_SETCAR (SCM_CAR (env), scm_cons (n, SCM_CAR (SCM_CAR (env))));
+         env = scm_cons (scm_cons (scm_cons (n, SCM_CAAR (env)),
+                                   SCM_CDAR (env)),
+                         SCM_CDR (env));
        break;
       }
     case SCM_BIT8(SCM_MAKISYM (0)):

Diagnosis

If scm_unmemocopy is called (e.g. from scm_backtrace) to unmemoize an
expression that has an internal define (i.e. SCM_IM_DEFINE) near the
top level of the expression, the code in unmemocopy can modify the
expression passed in.  The modification is such that an extra copy of
the symbol being defined is added on every call, thus:

  (((args) 4) ...)
  (((xxx args) 4) ...)
  (((xxx xxx args) 4) ...)

and so on, and this modification eventually causes some other code
that looks at the environment to SEGV.

The copy in scm_unmemocopy, which looks as though it might be intended
to fix this problem, doesn't work because it only copies the
environment's top-level pair, and it is the car of the car of the
environment that gets modified as just described.

Fix notes

Basically, avoid modifying the environment in hand by making new list
structure instead.  This is similar to almost all the other cases in
unmemocopy, which use EXTEND_ENV.  Fix isn't very elegant, though;
is there a nicer way of doing this?

Checks

1. make check passes.

2. Rerun of problem scenarios:

guile> (define (fnc args) (local-eval '(define xxx 3) (the-environment)))
guile> (fnc 4)
standard input:1:33: In expression (define xxx 3):
standard input:1:33: Bad define placement
ABORT: (misc-error)

Type "(backtrace)" to get more information or "(debug)" to enter the debugger.
guile> (debug)
This is the Guile debugger; type "help" for help.
There are 3 frames on the stack.

Frame 2 at standard input:1:33
        (define xxx 3)
debug> eval (the-environment)
;value: (((args) 4) #<eval-closure 40262bd0>)
debug> ba
In standard input:
   2: 0* [fnc 4]
   1: 1  [local-eval (define xxx 3) (((args) 4) #<eval-closure 40262bd0>)]
   1: 2* (define xxx 3)
debug> eval (the-environment)
;value: (((args) 4) #<eval-closure 40262bd0>)
guile> 

guile> (load "/home/neil/segf.scm")
guile> (assignments (command-line))
<unnamed port>: In expression (define a (option-ref options b ...)):
<unnamed port>: Bad define placement
ABORT: (misc-error)

Type "(backtrace)" to get more information or "(debug)" to enter the debugger.
guile> (backtrace )

Backtrace:
In standard input:
   2: 0* [assignments ("/usr/local/bin/guile")]
In /home/neil/segf.scm:
   2: 1  (let ((env #)) (for-each (lambda # #) (quote #)))
   3: 2  [for-each #<procedure #f (triplet)> ((a b c) (d e f))]
In unknown file:
   ?: 3* [#<procedure #f (triplet)> (a b c)]
In /home/neil/segf.scm:
   5: 4* (let ((x #) (y #) (z #)) (local-eval (quasiquote #) env))
   8: 5  [local-eval (define a #) (# #)]
In unknown file:
   ?: 6* (define a (option-ref options b c))

Type "(debug-enable 'backtrace)" if you would like a backtrace
automatically if an error occurs in the future.
guile> 







reply via email to

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