fix: check unix-ioctl return value before reading winsize

unix-ioctl returns NIL on failure, but the code still reads the
uninitialized alien winsize buffer, getting garbage values for
cols and rows (often 0 for rows). Now checks 'ok' before reading.
This commit is contained in:
2026-05-14 14:47:43 -04:00
parent aa73171c30
commit 9a54b7ade6
2 changed files with 29 additions and 34 deletions

View File

@@ -181,31 +181,29 @@ as a fallback when a keyword is not in *named-colors*.")
;; ioctl on stdout fd — fast, correct after SIGWINCH at runtime. ;; ioctl on stdout fd — fast, correct after SIGWINCH at runtime.
(multiple-value-bind (cols rows) (multiple-value-bind (cols rows)
(ignore-errors (ignore-errors
(let* ((+tiocgwinsz+ 21523) ; 0x5413 on Linux (let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
(winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
(unwind-protect (unwind-protect
(progn (let ((ok (sb-unix:unix-ioctl
(sb-unix:unix-ioctl (sb-sys:fd-stream-fd (backend-output-stream b)) (sb-sys:fd-stream-fd (backend-output-stream b))
+tiocgwinsz+ 21523 (sb-alien:alien-sap winsize))))
(sb-alien:alien-sap winsize)) (when ok
(values (sb-alien:deref winsize 1) ;; cols (values (sb-alien:deref winsize 1) ;; cols
(sb-alien:deref winsize 0))) ;; rows (sb-alien:deref winsize 0)))) ;; rows
(sb-alien:free-alien winsize)))) (sb-alien:free-alien winsize))))
(when (and cols rows (> cols 0) (> rows 0)) (when (and cols rows (> cols 0) (> rows 0))
(values cols rows))) (values cols rows)))
;; Direct ioctl on /dev/tty — opens the real controlling terminal. ;; Direct ioctl on /dev/tty.
(ignore-errors (ignore-errors
(let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0))) ; O_RDONLY (let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0)))
(when (and tty-fd (numberp tty-fd) (> tty-fd 0)) (when (and tty-fd (numberp tty-fd) (> tty-fd 0))
(unwind-protect (unwind-protect
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4))) (let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
(sb-unix:unix-ioctl tty-fd 21523 (sb-alien:alien-sap winsize)) (let ((ok (sb-unix:unix-ioctl tty-fd 21523
(sb-alien:alien-sap winsize))))
(when ok
(let ((cols (sb-alien:deref winsize 1)) (let ((cols (sb-alien:deref winsize 1))
(rows (sb-alien:deref winsize 0))) (rows (sb-alien:deref winsize 0)))
(sb-alien:free-alien winsize) (values cols rows)))))
(when (and (integerp cols) (integerp rows)
(> cols 0) (> rows 0))
(values cols rows))))
(sb-unix:unix-close tty-fd))))) (sb-unix:unix-close tty-fd)))))
(values 80 24))) (values 80 24)))

View File

@@ -40,31 +40,28 @@
;; ioctl on stdout fd — fast, correct after SIGWINCH at runtime. ;; ioctl on stdout fd — fast, correct after SIGWINCH at runtime.
(multiple-value-bind (cols rows) (multiple-value-bind (cols rows)
(ignore-errors (ignore-errors
(let* ((+tiocgwinsz+ 21523) (let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
(winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
(unwind-protect (unwind-protect
(progn (let ((ok (sb-unix:unix-ioctl
(sb-unix:unix-ioctl (sb-sys:fd-stream-fd (sb-sys:fd-stream-fd (backend-output-stream b))
(backend-output-stream b)) 21523 (sb-alien:alien-sap winsize))))
+tiocgwinsz+ (when ok
(sb-alien:alien-sap winsize))
(values (sb-alien:deref winsize 1) (values (sb-alien:deref winsize 1)
(sb-alien:deref winsize 0))) (sb-alien:deref winsize 0))))
(sb-alien:free-alien winsize)))) (sb-alien:free-alien winsize))))
(when (and cols rows (> cols 0) (> rows 0)) (when (and cols rows (> cols 0) (> rows 0))
(values cols rows))) (values cols rows)))
(ignore-errors (ignore-errors
(let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0))) ; O_RDONLY (let ((tty-fd (sb-unix:unix-open "/dev/tty" 0 0)))
(when (and tty-fd (numberp tty-fd) (> tty-fd 0)) (when (and tty-fd (numberp tty-fd) (> tty-fd 0))
(unwind-protect (unwind-protect
(let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4))) (let* ((winsize (sb-alien:make-alien sb-alien:unsigned-short 4)))
(sb-unix:unix-ioctl tty-fd 21523 (sb-alien:alien-sap winsize)) (let ((ok (sb-unix:unix-ioctl tty-fd 21523
(let ((cols (sb-alien:deref winsize 1)) (sb-alien:alien-sap winsize))))
(rows (sb-alien:deref winsize 0))) (when ok
(sb-alien:free-alien winsize) (values (sb-alien:deref winsize 1)
(when (and (integerp cols) (integerp rows) (sb-alien:deref winsize 0))))
(> cols 0) (> rows 0)) (sb-alien:free-alien winsize))
(values cols rows))))
(sb-unix:unix-close tty-fd))))) (sb-unix:unix-close tty-fd)))))
(values 80 24))) (values 80 24)))