Integer overflow in LOOP
ECL from current git master causes integer overflow in safe code inside LOOP
.
> (declaim (optimize (safety 3)))
((OPTIMIZE (SAFETY 3)))
> (compile nil (lambda ()
(loop for x of-type fixnum
from (1- most-positive-fixnum) to most-positive-fixnum
do (progn)
finally (print x))))
;;; OPTIMIZE levels: Safety=3, Space=0, Speed=3, Debug=0
;;;
;;; End of Pass 1.
#<compiled-function 0x555ccc1614c0>
NIL
NIL
> (funcall *)
-2305843009213693952
This is likely due to ext:assume-right-type
declaration used in macro loop-unsafe
.
> (declaim (optimize (safety 3)))
((OPTIMIZE (SAFETY 3)))
> (compile nil (lambda () (let ((x most-positive-fixnum)) (declare (fixnum x)) (locally (declare (ext:assume-right-type)) (setq x (1+ x))))))
;;; OPTIMIZE levels: Safety=3, Space=0, Speed=3, Debug=0
;;;
;;; End of Pass 1.
#<compiled-function 0x555ccc118c40>
NIL
NIL
> (funcall *)
-2305843009213693952
This is directly related to ANSI-TEST LOOP.1.40
that ECL currently fails:
;;; Test that the index variable achieves the inclusive
;;; upper bound, but does not exceed it.
(deftest loop.1.40
(loop for x from 1 to 5 do (progn) finally (return x))
5) ;; ECL returns 6 instead
And to ANSI-TEST LOOP.1.39
that, I assume, was meant to be fixed by introducing the LOOP-UNSAFE
macro:
;;; The following provides an example where an incorrect
;;; implementation will assign X an out-of-range value
;;; at the end.
(deftest loop.1.39
(loop for x of-type (integer 1 5) from 1 to 5 collect x)
(1 2 3 4 5)) ;; ECL passes this test, but X is internally set to an out-of-range value
In an iteration control clause, the for or as construct causes termination when the supplied limit is reached. That is, iteration continues until the value var is stepped to the exclusive or inclusive limit supplied by form2.
For these clauses, iteration terminates when a local variable reaches some supplied value or when some other loop clause terminates iteration.