bug#81562: [PATCH] Restore current_buffer when window_text_pixel_size fails
Maxim Wayne <[email protected]>
| Newsgroups | gmane.emacs.bugs |
|---|---|
| Message-ID | <CADtsJB039puj-1mSKGpvaB=63=-qSCKjO=PJMXr7s_H5dxLGWg@mail.gmail.com> |
Thanks. I've reworked the patch to validate the arguments up front, as you suggested. FROM, TO, X-LIMIT, Y-LIMIT and MODE-LINES are now checked with the CHECK_* macros at the beginning of Fwindow_text_pixel_size, before any buffer switch. For MODE-LINES, my check limits the value to the three symbols: mode-line, tab-line and header-line -- please tell me if you prefer checking only the type. The patch adds two tests: one verifies that an invalid FROM argument signals an error before the buffer switch, the other covers the rest of the new checks. Both fail on Emacs 30.2 and pass with the patch applied. The patch is attached; it is against current master (commit cb22cfe1414). On Thu, Aug 6, 2026 at 12:25 PM Eli Zaretskii <[email protected]> wrote: > > From: Maxim Wayne <[email protected]> > > Date: Wed, 5 Aug 2026 20:26:45 +0800 > > > > The window-text-pixel-size function temporarily switches the > > current_buffer pointer; if the function fails, the pointer is not > > switched back. > > To reproduce: When current_buffer = buf_a while the window displays > > buf_b, giving a cons whose cdr is not an integer > > as the FROM argument to window-text-pixel-size, the function fails and > > current_buffer doesn't switch back to buf_a. > > The included test fails on Emacs 30.2 and passes on the patched code. > > Please see the attachment for the patch. The patch is against current > > master (commit 602cde3). > > Thanks, but this is not the correct solution. Our conventions are to > validate the arguments of the primitives up front, using the various > CHECK_* macros (like CHECK_NUMBER, CHECK_BUFFER, etc.), and if those > validations fail, signal an error before performing any significant > processing (including switching to another buffer). It is true that > this primitive fails to perform such checks, but the correct solution > is to add them, not to recover from errors the low-level code might > signal due to invalid arguments. > > Would you like to submit a patch along those lines? >
0001-Validate-arguments-of-window-text-pixel-size-up-fron.patch
(application/octet-stream, 4.6 KB)
From 208c486db2d54016ebea6f8caaa34ecc84ee4f0e Mon Sep 17 00:00:00 2001 From: SkyCanvas <[email protected]> Date: Sun, 16 Aug 2026 22:03:05 +0800 Subject: [PATCH] Validate arguments of window-text-pixel-size up front In the b != current_buffer branch, if window_text_pixel_size encounters an error (such as receiving an argument of the wrong type), the current_buffer pointer remains at b and is not correctly switched back. FROM, TO, X-LIMIT, Y-LIMIT and MODE-LINES are now checked with CHECK_* macros before the buffer switch. * src/xdisp.c (Fwindow_text_pixel_size): Validate arguments before calling window_text_pixel_size. * test/src/xdisp-tests.el (xdisp-tests--window-text-pixel-size-args-before-switch) (xdisp-tests--window-text-pixel-size-invalid-args): New tests. --- src/xdisp.c | 30 +++++++++++++++++++++++++++ test/src/xdisp-tests.el | 46 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/src/xdisp.c b/src/xdisp.c index beb8d980ee3..12f8627c650 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -12128,6 +12128,36 @@ DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_siz struct buffer *old_b = NULL; Lisp_Object value; + if (!NILP (from) && !EQ (from, Qt)) + { + if (CONSP (from)) + { + CHECK_TYPE (INTEGERP (XCAR (from)) || MARKERP (XCAR (from)), + Qinteger_or_marker_p, XCAR (from)); + CHECK_FIXNUM (XCDR (from)); + } + else + CHECK_TYPE (INTEGERP (from) || MARKERP (from), + Qinteger_or_marker_p, from); + } + + if (!NILP (to) && !EQ (to, Qt)) + CHECK_TYPE (INTEGERP (to) || MARKERP (to), Qinteger_or_marker_p, to); + + if (!NILP (x_limit) && !EQ (x_limit, Qt)) + CHECK_FIXNAT (x_limit); + + if (!NILP (y_limit)) + CHECK_FIXNAT (y_limit); + + if (!NILP (mode_lines) && !EQ (mode_lines, Qt)) + { + CHECK_SYMBOL (mode_lines); + if (!EQ (mode_lines, Qmode_line) && !EQ (mode_lines, Qtab_line) + && !EQ (mode_lines, Qheader_line)) + error ("MODE-LINES must be mode-line, tab-line or header-line"); + } + if (b != current_buffer) { old_b = current_buffer; diff --git a/test/src/xdisp-tests.el b/test/src/xdisp-tests.el index 8eb57253972..3722dadb1cc 100644 --- a/test/src/xdisp-tests.el +++ b/test/src/xdisp-tests.el @@ -213,4 +213,50 @@ xdisp-test-format-mode-line (should (equal m1 m2)) (should (equal s1 s2))))) +(ert-deftest xdisp-tests--window-text-pixel-size-args-before-switch () + "Invalid arguments must be rejected before switching to WINDOW's buffer." + (let ((buf-a (generate-new-buffer "buf-a")) + (buf-b (generate-new-buffer "buf-b"))) + (unwind-protect + (progn + (with-current-buffer buf-b + (insert "test content for window-text-pixel-size")) + (set-window-buffer (selected-window) buf-b) + (set-buffer buf-a) + (should-error + (window-text-pixel-size (selected-window) + (cons 1 "not-a-fixnum") + nil nil nil nil nil) + :type 'wrong-type-argument) + (should (eq (current-buffer) buf-a))) + (ignore-errors (kill-buffer buf-a)) + (ignore-errors (kill-buffer buf-b))))) + +(ert-deftest xdisp-tests--window-text-pixel-size-invalid-args () + ;; FROM must be nil, t, a position (integer or marker), or a cons + ;; (POSITION . VERTICAL-OFFSET) where VERTICAL-OFFSET is a fixnum. + (should-error (window-text-pixel-size nil "foo") + :type 'wrong-type-argument) + (should-error (window-text-pixel-size nil '("foo" . 1)) + :type 'wrong-type-argument) + (should-error (window-text-pixel-size nil '(1 . "foo")) + :type 'wrong-type-argument) + ;; TO must be nil, t, or a position. + (should-error (window-text-pixel-size nil nil "foo") + :type 'wrong-type-argument) + ;; X-LIMIT must be nil, t, or a nonnegative fixnum. + (should-error (window-text-pixel-size nil nil nil "foo") + :type 'wrong-type-argument) + (should-error (window-text-pixel-size nil nil nil -1) + :type 'wrong-type-argument) + ;; Y-LIMIT must be nil or a nonnegative fixnum; unlike X-LIMIT, + ;; t is not valid. + (should-error (window-text-pixel-size nil nil nil nil t) + :type 'wrong-type-argument) + ;; MODE-LINES must be nil, t, or one of the three line symbols. + (should-error (window-text-pixel-size nil nil nil nil nil 'mod-line)) + ;; Valid arguments must still be accepted. + (should (consp (window-text-pixel-size nil '(1 . 0)))) + (should (consp (window-text-pixel-size nil nil nil t nil 'mode-line)))) + ;;; xdisp-tests.el ends here -- 2.55.0