errors from dynamic-extent specialized arrays

Bug #1472785 reported by 3b
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
Fix Released
Undecided
Unassigned

Bug Description

specialized arrays with element size < 64 bits cause problems on x8664 linux and windows in 1.2.13.2 and 1.2.13.30, but not on arm.
same tests work OK on 1.2.4.80 linux x8664 (possibly happened somewhere between 1.2.5 and 1.2.10 from discussion on #lisp)

(defun foo (c)
  (let ((s (make-string 1 :initial-element c)))
    (declare (dynamic-extent s))
    (write-sequence s *standard-output*)
    nil))

(foo #\a)

errors with

  The value #<invalid object #x7FFFD66CF74F> is not of type SEQUENCE.

similar error with MAKE-ARRAY and :ELEMENT-TYPEs CHARACTER, (UNSIGNED-BYTE 8), SINGLE-FLOAT, etc

Without the declaration, or with DOUBLE-FLOAT or (UNSIGNED-BYTE 64) array it runs as expected.

(defun foo2 (c)
  (let ((s (make-array 1 :element-type 'single-float :initial-element c)))
    (declare (dynamic-extent s))
    (1+ (elt s 0))))

(foo2 1.0)

errors with EXCEPTION_ACCESS_VIOLATION or SB-SYS:MEMORY-FAULT-ERROR depending on OS

Again, error only happens with <64-bit types and DYNAMIC-EXTENT declaration.

Original test case is from iolib, http://paste.lisp.org/display/151209#1

3b (00003b)
tags: added: regression
Revision history for this message
Alastair Bridgewater (alastair-bridgewater) wrote :

Here's another test case, not so dependent on the FILL transform:

(defun bar (x)
  (let ((y (let ((z (cons nil nil)))
             (let ((i 0))
               (tagbody
                b1
                  (when (= x i) (go b2))
                  (incf i)
                  (go b1)
                b2))
             z))
        (w (cons t t)))
    (declare (dynamic-extent y w))
    (eq y w)))

Due to the bug (BAR 0) => NIL, but (BAR 1) => T.

The actual problem is in src/compiler/stack.lisp, BACK-PROPAGATE-ONE-DX-LVAR, where it tries to prevent falling into an infinite loop by refusing to traverse a block twice, which is wrong. Mea culpa. The correct thing to do is to refuse to repeat a transition between two blocks. That way, it can still visit a block multiple times, but because it can't take the same path twice it will still terminate.

Thanks to stassats for narrowing this down to a stack-analysis issue.

Changed in sbcl:
status: New → Fix Committed
Changed in sbcl:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.