From debbugs-submit-bounces@debbugs.gnu.org Sun Sep 11 12:00:01 2022 Received: (at submit) by debbugs.gnu.org; 11 Sep 2022 16:00:01 +0000 Received: from localhost ([127.0.0.1]:43233 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oXPNI-000483-Hs for submit@debbugs.gnu.org; Sun, 11 Sep 2022 12:00:01 -0400 Received: from lists.gnu.org ([209.51.188.17]:36942) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oXPNH-00047v-23 for submit@debbugs.gnu.org; Sun, 11 Sep 2022 11:59:59 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35564) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oXPNG-0004Pf-TM for bug-gnu-emacs@gnu.org; Sun, 11 Sep 2022 11:59:58 -0400 Received: from mail-wr1-x429.google.com ([2a00:1450:4864:20::429]:43785) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oXPNE-0000E8-J0 for bug-gnu-emacs@gnu.org; Sun, 11 Sep 2022 11:59:58 -0400 Received: by mail-wr1-x429.google.com with SMTP id t7so11591955wrm.10 for ; Sun, 11 Sep 2022 08:59:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:message-id:date:subject:to:from:from:to:cc:subject :date; bh=UNO9BB5OtgCBLdGiItBqPiluZw3gxcduLaHuv3pHiqE=; b=LZFPC0sSfkOX8+q1fOd8d7mny+ltwDqPeP68xNvrm4TbkOSe4rhHVl/JY5XXlBpv0W peM67b5FqvQ8aF/l/soQz6ec3UdPb0phqkPTSC+WxJrk+h4SRcKdPxfj4Xom9tXLuyy0 15V7dE4pnTs9GIVdB0YgTdgMpWSwW4t86YxhkZ6oXSlwsnxOJ9rCx0YcYid3STpyhL7O CSlgNbVVCFzO9BbXocWrJiEFnYov6G4jIroqhioAC87BDkTGvDwyVKS/ghxjNeIeiedV 2gyqKl5dvwfI+h3cv/JacpUtN7YTrBK2HsJJOOhjzNzl0cra8PG8Md3DvEJpxrXfQ59I 0CbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=mime-version:message-id:date:subject:to:from:x-gm-message-state :from:to:cc:subject:date; bh=UNO9BB5OtgCBLdGiItBqPiluZw3gxcduLaHuv3pHiqE=; b=JriTG2uYakER0opT77q7jP6EQOYrdKUP9U/iP+S3ohXy9i81WB7kuVOTIpVmPvcBtU U9LEEwavjnZ2bO/B3t/kVYOHVcA7ENMXzg8yiCHGBjYx66NwmB7V6K24xkeh1xOVkukx MMVpVBPBfMYH3Aw/dfoeYLIHEn9RC7hVgzTQExd3zzR7LyysLHmAcY9jLollANEabofG cgK3/dZ6d5qHMZR1cnRjPeKzMOWQBiCfFZXhQXen/1zyunIsx2/+AYMJna99e/zkHn0f /ZD4prtZWIPeGWPBmqHDoDu5EMMs+LIVyrVMNL+QM4AcCztRb2JQwFI9jdco98Yg187J tDiQ== X-Gm-Message-State: ACgBeo3NXBPdwnGSE7NB9xa970Nky/rxnPodR7U6cEm+lKEY4DRicPM9 wYCEDSPPenZCc4sd0/iXR56SMnOSzxE= X-Google-Smtp-Source: AA6agR6v8Zepyd25oG84QXZyEsH20CUlo+1B0fT4md51Zt6AW+RTKFkxRULxRNYebu/NdZX5SWZZdA== X-Received: by 2002:adf:ea4a:0:b0:228:635a:d491 with SMTP id j10-20020adfea4a000000b00228635ad491mr13244322wrn.137.1662911994100; Sun, 11 Sep 2022 08:59:54 -0700 (PDT) Received: from amdahl30 ([2a01:e0a:253:fe0:2ef0:5dff:fed2:7b49]) by smtp.gmail.com with ESMTPSA id p15-20020a5d48cf000000b00226dedf1ab7sm5254075wrs.76.2022.09.11.08.59.52 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 11 Sep 2022 08:59:53 -0700 (PDT) From: =?utf-8?Q?K=C3=A9vin_Le_Gouguec?= To: bug-gnu-emacs@gnu.org Subject: 29.0.50; Fix "Invalid search bound (wrong side of point)" error in replace-*-in-region Date: Sun, 11 Sep 2022 17:59:52 +0200 Message-ID: <87r10hc35z.fsf@gmail.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=2a00:1450:4864:20::429; envelope-from=kevin.legouguec@gmail.com; helo=mail-wr1-x429.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: -1.3 (-) X-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -2.3 (--) --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable The replace-{string,regexp}-in-region functions can throw an error if the replacement text is large compared to the replaced text: (point) might move beyond END, which means the underlying {,re-}search-forward functions are called with BOUND "on the wrong side of point". Recipe from emacs -Q: 1. Open *scratch* and type: (with-temp-buffer (insert "foo bar baz") (replace-regexp-in-region "ba." "quux corge grault" (point-min) (point-max))) 2. C-j Backtrace attached, with suggested patch (including tests) to update END to reflect the displacement after each replacement. I'm assuming these are the semantics we prefer, since users can't call these functions with (> end (point-max)) to guard against that error, but we could also just bail as soon as (> (point) end). That would prevent the error, but it could cause us to return early and miss some matches. The patch does change the semantics in the opposite situation (and the tests check for the new behaviour): when the replacement is shorter than the original text, it is currently possible for matches that were originally beyond END to become reachable; the patch prevents that. I'm assuming that's TRT because if users say "replace no further than THERE", they're probably talking about a point of interest (end of a line, a function=E2=80=A6) rather than the numeric value of THERE. If we want this change to go in: should we call it out in the docstrings and/or "(elisp) Search and Replace" and/or in NEWS? FWIW: I've seen no regression with a full "make check", but I've just written the patch, so I haven't had the time to live with it and see what breaks. In GNU Emacs 29.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.34, cairo version 1.16.0) of 2022-09-10 built on amdahl30 Repository revision: 433fc8bebfef40130bf62f17e5349560b62e566e Repository branch: master Windowing system distributor 'The X.Org Foundation', version 11.0.12101004 System Description: openSUSE Tumbleweed Configured using: 'configure --with-cairo --with-gconf --with-sqlite3 --with-xinput2' Configured features: ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS WEBP X11 XDBE XIM XINPUT2 XPM GTK3 ZLIB Important settings: value of $LANG: en_US.UTF-8 value of $XMODIFIERS: @im=3Dlocal locale-coding-system: utf-8-unix --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Update-search-bound-while-replacing-matches-in-repla.patch >From f69158a344e5c95b0dc788bcaafcf87eda21a421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Le=20Gouguec?= Date: Sun, 11 Sep 2022 16:15:38 +0200 Subject: [PATCH] Update search bound while replacing matches in replace-*-in-region Not doing so can lead to two surprising results: (1) when REPLACEMENT is much larger than the original text, point might move beyond END, which causes the search functions to error out; (2) when REPLACEMENT is much shorter than the original text, the search functions might find matches that the user did not intend, as they were beyond END before the replacements happened. * lisp/subr.el (replace-string-in-region, replace-regexp-in-region): Update END while replacing matches. * test/lisp/subr-tests.el (test-replace-string-in-region): Add regression tests. --- lisp/subr.el | 18 ++++++++++++------ test/lisp/subr-tests.el | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/lisp/subr.el b/lisp/subr.el index 686189e69b..10b3bdcd8d 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -4220,12 +4220,15 @@ replace-string-in-region (setq end (point-max))) (save-excursion (let ((matches 0) - (case-fold-search nil)) + (case-fold-search nil) + end-of-match) (goto-char start) - (while (search-forward string end t) + (while (setq end-of-match (search-forward string end t)) (delete-region (match-beginning 0) (match-end 0)) (insert replacement) - (setq matches (1+ matches))) + (setq matches (1+ matches) + end (+ end + (- (point) end-of-match)))) (and (not (zerop matches)) matches)))) @@ -4255,11 +4258,14 @@ replace-regexp-in-region (setq end (point-max))) (save-excursion (let ((matches 0) - (case-fold-search nil)) + (case-fold-search nil) + end-of-match) (goto-char start) - (while (re-search-forward regexp end t) + (while (setq end-of-match (re-search-forward regexp end t)) (replace-match replacement t) - (setq matches (1+ matches))) + (setq matches (1+ matches) + end (+ end + (- (point) end-of-match)))) (and (not (zerop matches)) matches)))) diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index 4310b7291a..3011713210 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el @@ -968,7 +968,21 @@ test-replace-string-in-region (insert "Foo bar zot foobar") (should (= (replace-string-in-region "Foo" "new" (point-min)) 1)) - (should (equal (buffer-string) "new bar zot foobar")))) + (should (equal (buffer-string) "new bar zot foobar"))) + + (with-temp-buffer + (insert "foo bar baz") + (should (= (replace-string-in-region "ba" "quux corge grault" (point-min)) + 2)) + (should (equal (buffer-string) + "foo quux corge graultr quux corge graultz"))) + + (with-temp-buffer + (insert "foo bar bar") + (should (= (replace-string-in-region " bar" "" (point-min) 8) + 1)) + (should (equal (buffer-string) + "foo bar")))) (ert-deftest test-replace-regexp-in-region () (with-temp-buffer @@ -991,7 +1005,21 @@ test-replace-regexp-in-region (insert "Foo bar zot foobar") (should (= (replace-regexp-in-region "Fo+" "new" (point-min)) 1)) - (should (equal (buffer-string) "new bar zot foobar")))) + (should (equal (buffer-string) "new bar zot foobar"))) + + (with-temp-buffer + (insert "foo bar baz") + (should (= (replace-regexp-in-region "ba." "quux corge grault" (point-min)) + 2)) + (should (equal (buffer-string) + "foo quux corge grault quux corge grault"))) + + (with-temp-buffer + (insert "foo bar bar") + (should (= (replace-regexp-in-region " bar" "" (point-min) 8) + 1)) + (should (equal (buffer-string) + "foo bar")))) (ert-deftest test-with-existing-directory () (let ((dir (make-temp-name "/tmp/not-exist-"))) -- 2.37.3 --=-=-= Content-Type: text/plain Content-Disposition: attachment; filename=invalid-search-bound.backtrace Debugger entered--Lisp error: (wrong-type-argument sequencep 1) replace-regexp-in-string("ba." "quux corge grault" 1 12) (progn (insert "foo bar baz") (replace-regexp-in-string "ba." "quux corge grault" (point-min) (point-max))) (unwind-protect (progn (insert "foo bar baz") (replace-regexp-in-string "ba." "quux corge grault" (point-min) (point-max))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer))) (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn (insert "foo bar baz") (replace-regexp-in-string "ba." "quux corge grault" (point-min) (point-max))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer)))) (let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn (insert "foo bar baz") (replace-regexp-in-string "ba." "quux corge grault" (point-min) (point-max))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer))))) (progn (let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn (insert "foo bar baz") (replace-regexp-in-string "ba." "quux corge grault" (point-min) (point-max))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer)))))) eval((progn (let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn (insert "foo bar baz") (replace-regexp-in-string "ba." "quux corge grault" (point-min) (point-max))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer)))))) t) elisp--eval-last-sexp(t) eval-last-sexp(t) eval-print-last-sexp(nil) funcall-interactively(eval-print-last-sexp nil) call-interactively(eval-print-last-sexp nil nil) command-execute(eval-print-last-sexp) --=-=-=-- From debbugs-submit-bounces@debbugs.gnu.org Sun Sep 11 12:17:30 2022 Received: (at 57733) by debbugs.gnu.org; 11 Sep 2022 16:17:31 +0000 Received: from localhost ([127.0.0.1]:43249 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oXPeE-0004aP-Ng for submit@debbugs.gnu.org; Sun, 11 Sep 2022 12:17:30 -0400 Received: from quimby.gnus.org ([95.216.78.240]:42352) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oXPeC-0004aC-OR for 57733@debbugs.gnu.org; Sun, 11 Sep 2022 12:17:29 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Content-Transfer-Encoding:Content-Type:MIME-Version:Message-ID :Date:References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=NzuAQWkqDxCsfp4RtuOdupt+IszL8Ul4xvwTKNHGpZI=; b=EJ5G42d8+C1mFX8yAkV4ileFz/ J+oOFHLcNAN8y8GWLCX176CiKRcvIdDCWC/9aslMUUmOmrPTrDtfU4o1b9iu3PHjn747iy8aGmGBw aqYISyyXxettjU2XdImT4uSUzPe7RuZw10KZINsYl6yfVzNAPYKgkJuPiiZreeGlqY4A=; Received: from [84.212.220.105] (helo=joga) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oXPe4-0006AP-5u; Sun, 11 Sep 2022 18:17:22 +0200 From: Lars Ingebrigtsen To: =?utf-8?Q?K=C3=A9vin?= Le Gouguec Subject: Re: bug#57733: 29.0.50; Fix "Invalid search bound (wrong side of point)" error in replace-*-in-region In-Reply-To: <87r10hc35z.fsf@gmail.com> (=?utf-8?Q?=22K=C3=A9vin?= Le Gouguec"'s message of "Sun, 11 Sep 2022 17:59:52 +0200") References: <87r10hc35z.fsf@gmail.com> Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAABGdBTUEAALGPC/xhBQAAACBj SFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAD1BMVEVcf6EwIia5WBvm pSf///883WZnAAAAAWJLR0QEj2jZUQAAAAd0SU1FB+YJCxAQFnTosz8AAAGCSURBVDjLdZPtmcQg CIT1KnDYBhZoYKP993aAGM19+OyPDW8GZCCl1FYqIO8uosOOxOFSSrN4i6cDXAnwJSzk8dHFtTdo YH4FGBvADxHrSJIACZDxsRTVJVWyxFAHMoEXUZH5ukYuvoFFuuxcdQGKVy1Nlg9gP8hKMxVvB0ZA Gs/3dROg0JCxKoQp8MatiA7deawNA81Iq9aDDL2BdETf1qEsSZ/uIp0yb1XGEzghz6t3ZZE2U2GP KQVvzGn4CJZVAay3lgqWZW6AnYpkhn8CFmia5XIkIDDBJxSALL6AxV0hIYjQUni+WJ0u8/EEElcF nwovR8jtfAANrxEK3gAx6gsc96434LlSTOFAu45Uc0iic3y7j7k5yt41DboVsVT+aoB+Arejx6fB WvkA7oaH7cpadx/UfXNNxebf52iQIr1ZBQF9sIHtUSxPN5+obkACl1g++/cqh8K+M7XfkLl8D+Ci i7FPCl++VmFrqw9AbkXMtD4V6PhxFiD+Bwhdf4Nf5xs1g3+5WEeTlQAAACV0RVh0ZGF0ZTpjcmVh dGUAMjAyMi0wOS0xMVQxNjoxNjoyMiswMDowMPGB7wUAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjIt MDktMTFUMTY6MTY6MjIrMDA6MDCA3Fe5AAAAAElFTkSuQmCC X-Now-Playing: Breathless's _See Those Colours Fly_: "My Heart And I" Date: Sun, 11 Sep 2022 18:17:17 +0200 Message-ID: <87illtdgxe.fsf@gnus.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: Kévin Le Gouguec writes: > Backtrace attached, with suggested patch (including tests) to update END > to reflect the displacement after each replacement. Perhaps a simpler solution would to just be to use `save-restriction'+`narrow-to-region' first and then don't use an END in the search? Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 57733 Cc: 57733@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) K=C3=A9vin Le Gouguec writes: > Backtrace attached, with suggested patch (including tests) to update END > to reflect the displacement after each replacement. Perhaps a simpler solution would to just be to use `save-restriction'+`narrow-to-region' first and then don't use an END in the search? From debbugs-submit-bounces@debbugs.gnu.org Sun Sep 11 13:09:14 2022 Received: (at 57733) by debbugs.gnu.org; 11 Sep 2022 17:09:14 +0000 Received: from localhost ([127.0.0.1]:43300 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oXQSI-00065x-3J for submit@debbugs.gnu.org; Sun, 11 Sep 2022 13:09:14 -0400 Received: from mail-wm1-f54.google.com ([209.85.128.54]:55924) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oXQSG-00065j-Im for 57733@debbugs.gnu.org; Sun, 11 Sep 2022 13:09:13 -0400 Received: by mail-wm1-f54.google.com with SMTP id d5so5591317wms.5 for <57733@debbugs.gnu.org>; Sun, 11 Sep 2022 10:09:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:from:to:cc:subject:date; bh=FV3RLRlGqloIPJ+d9tcW8loGdwS8+vaONJg0c6e1Hqc=; b=qMILcGnpHEBKjebGLq3QEw9d6YRyTtOaSH/IJGLEI6AKfLaGY2E6npXo5GqXJ+/+0r KFlhpPgeTeBYPFdujKKUIKCj+a3y+6nh9AGFWUww8Q+9P3S1ppXlKKUozLzo7qalQgt0 /Ss1VWSlj+eZus8KnX3c2DoDSpm94gzXNgT8uzqMIB8vMElrDnrJHQT5iP9ngi10BXHl jwxWveqABp8pqdCrPg/aEoeYVC8OmbxfFhTUnrCrPKucEeMpcv1Itgco6cCI+w3PVeuH S8yUFeW3lC2rPvzR6JfemUCqcmd9ZyBdsOn+Zyd1rI0j0H0ctQ+XLDj/4vz+eTEXknM8 /lnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=mime-version:user-agent:message-id:date:references:in-reply-to :subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date; bh=FV3RLRlGqloIPJ+d9tcW8loGdwS8+vaONJg0c6e1Hqc=; b=L1Jo88CtVgVvXEjHjLiDzfo556jDBwdwrvmHNR9USYHs7Zn4VpgzMDfr+Vv2/PBsVe EpEu6tyYOLllAPmsGEJRv3kQZtqTzPWUMVMITWZRqCrTxdB/mwQ3nqgY+wvtUt+B96bD qOF0MtXJlUuQUoo25aDDztvnUt2bRPb4a8t7ITnA6FaBdAjitB4XL7TW5Bt2pfgj2hhf 1ceR98PynV6loVVPn0/e2MBourSoLcdphfF0tPReiupgbMOYafhU8zm30LPG6wTDe6k3 2SUT8KWhJlUg4h/iWtd7gF80+PqyadA5ApsaubA60OUrZTIhlfBz978I6MpLCWPACW+r Lf1Q== X-Gm-Message-State: ACgBeo0rOEkq6HsnvFSkuxjJVCVg96NnVxZ7+iZY07+g5JlmQFL8RDRm HbBFKOKVZViNk6KQ04WXOCabhWcgQRg= X-Google-Smtp-Source: AA6agR7vVXtZMpRVfpJUTEGbJjFnD33j/EzdTz2WqhGEi4ZNhbTu5aODcx7fYPOgLyxV9ZRXJA5spg== X-Received: by 2002:a05:600c:1d14:b0:3a5:e8ba:f394 with SMTP id l20-20020a05600c1d1400b003a5e8baf394mr11402646wms.137.1662916146135; Sun, 11 Sep 2022 10:09:06 -0700 (PDT) Received: from amdahl30 ([2a01:e0a:253:fe0:2ef0:5dff:fed2:7b49]) by smtp.gmail.com with ESMTPSA id 11-20020a05600c020b00b003b4868eb6bbsm1221783wmi.23.2022.09.11.10.09.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 11 Sep 2022 10:09:05 -0700 (PDT) From: =?utf-8?Q?K=C3=A9vin_Le_Gouguec?= To: Lars Ingebrigtsen Subject: Re: bug#57733: 29.0.50; Fix "Invalid search bound (wrong side of point)" error in replace-*-in-region In-Reply-To: <87illtdgxe.fsf@gnus.org> (Lars Ingebrigtsen's message of "Sun, 11 Sep 2022 18:17:17 +0200") References: <87r10hc35z.fsf@gmail.com> <87illtdgxe.fsf@gnus.org> Date: Sun, 11 Sep 2022 19:09:04 +0200 Message-ID: <87illtbzyn.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 57733 Cc: 57733@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --=-=-= Content-Type: text/plain Lars Ingebrigtsen writes: > Perhaps a simpler solution would to just be to use > `save-restriction'+`narrow-to-region' first and then don't use an END in > the search? That makes a lot of sense, thanks; new patch attached. --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Restrict-replace-in-region-to-the-bounds-defined-by-.patch >From b5cc63cfd89f695067e9bb3a0135aded615557f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Le=20Gouguec?= Date: Sun, 11 Sep 2022 16:15:38 +0200 Subject: [PATCH] Restrict replace-*-in-region to the bounds defined by caller And call the corresponding *search-forward functions without giving them a bound. The previous code can lead to two surprising outcomes: (1) when REPLACEMENT is much larger than the original text, point might move beyond END, which causes the search functions to error out; (2) when REPLACEMENT is much shorter than the original text, the search functions might find matches that the user did not intend, as they were beyond END before the replacements happened. Fixes bug#57733. * lisp/subr.el (replace-string-in-region, replace-regexp-in-region): Narrow to region before iterating over matches, instead of giving a bound to the search functions. * test/lisp/subr-tests.el (test-replace-string-in-region): Add regression tests. --- lisp/subr.el | 38 +++++++++++++++++++++----------------- test/lisp/subr-tests.el | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/lisp/subr.el b/lisp/subr.el index 686189e69b..8769fec2b9 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -4219,15 +4219,17 @@ replace-string-in-region (error "End after end of buffer")) (setq end (point-max))) (save-excursion - (let ((matches 0) - (case-fold-search nil)) - (goto-char start) - (while (search-forward string end t) - (delete-region (match-beginning 0) (match-end 0)) - (insert replacement) - (setq matches (1+ matches))) - (and (not (zerop matches)) - matches)))) + (goto-char start) + (save-restriction + (narrow-to-region start end) + (let ((matches 0) + (case-fold-search nil)) + (while (search-forward string nil t) + (delete-region (match-beginning 0) (match-end 0)) + (insert replacement) + (setq matches (1+ matches))) + (and (not (zerop matches)) + matches))))) (defun replace-regexp-in-region (regexp replacement &optional start end) "Replace REGEXP with REPLACEMENT in the region from START to END. @@ -4254,14 +4256,16 @@ replace-regexp-in-region (error "End after end of buffer")) (setq end (point-max))) (save-excursion - (let ((matches 0) - (case-fold-search nil)) - (goto-char start) - (while (re-search-forward regexp end t) - (replace-match replacement t) - (setq matches (1+ matches))) - (and (not (zerop matches)) - matches)))) + (goto-char start) + (save-restriction + (narrow-to-region start end) + (let ((matches 0) + (case-fold-search nil)) + (while (re-search-forward regexp nil t) + (replace-match replacement t) + (setq matches (1+ matches))) + (and (not (zerop matches)) + matches))))) (defun yank-handle-font-lock-face-property (face start end) "If `font-lock-defaults' is nil, apply FACE as a `face' property. diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index 4310b7291a..3011713210 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el @@ -968,7 +968,21 @@ test-replace-string-in-region (insert "Foo bar zot foobar") (should (= (replace-string-in-region "Foo" "new" (point-min)) 1)) - (should (equal (buffer-string) "new bar zot foobar")))) + (should (equal (buffer-string) "new bar zot foobar"))) + + (with-temp-buffer + (insert "foo bar baz") + (should (= (replace-string-in-region "ba" "quux corge grault" (point-min)) + 2)) + (should (equal (buffer-string) + "foo quux corge graultr quux corge graultz"))) + + (with-temp-buffer + (insert "foo bar bar") + (should (= (replace-string-in-region " bar" "" (point-min) 8) + 1)) + (should (equal (buffer-string) + "foo bar")))) (ert-deftest test-replace-regexp-in-region () (with-temp-buffer @@ -991,7 +1005,21 @@ test-replace-regexp-in-region (insert "Foo bar zot foobar") (should (= (replace-regexp-in-region "Fo+" "new" (point-min)) 1)) - (should (equal (buffer-string) "new bar zot foobar")))) + (should (equal (buffer-string) "new bar zot foobar"))) + + (with-temp-buffer + (insert "foo bar baz") + (should (= (replace-regexp-in-region "ba." "quux corge grault" (point-min)) + 2)) + (should (equal (buffer-string) + "foo quux corge grault quux corge grault"))) + + (with-temp-buffer + (insert "foo bar bar") + (should (= (replace-regexp-in-region " bar" "" (point-min) 8) + 1)) + (should (equal (buffer-string) + "foo bar")))) (ert-deftest test-with-existing-directory () (let ((dir (make-temp-name "/tmp/not-exist-"))) -- 2.37.3 --=-=-=-- From debbugs-submit-bounces@debbugs.gnu.org Sun Sep 11 13:55:27 2022 Received: (at 57733) by debbugs.gnu.org; 11 Sep 2022 17:55:27 +0000 Received: from localhost ([127.0.0.1]:43342 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oXRB1-0007Ea-0c for submit@debbugs.gnu.org; Sun, 11 Sep 2022 13:55:27 -0400 Received: from quimby.gnus.org ([95.216.78.240]:42978) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oXRAz-0007EG-4D for 57733@debbugs.gnu.org; Sun, 11 Sep 2022 13:55:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Content-Transfer-Encoding:Content-Type:MIME-Version:Message-ID :Date:References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=DIiaUiA9V71lDhpEC/hwT2YiSFa4hNOuyIPRa1UnINI=; b=HNNiSdCBtahYdX0Ef4uE23VCo2 NChGNHT7CQ1Qp2VlOIUh3gn9euEDzap8Y0W4quiOZybXDLK6LcCzZ9nDLwnRYiyn5TbwOIqHYLSQM +ElwFHLqsY57eazU9u4uEpasLyAeYGqHBPOsC5mE71FA1JZEcbr/1xkD52JWJU4ZRY5g=; Received: from [84.212.220.105] (helo=joga) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oXRAp-0006kG-58; Sun, 11 Sep 2022 19:55:18 +0200 From: Lars Ingebrigtsen To: =?utf-8?Q?K=C3=A9vin?= Le Gouguec Subject: Re: bug#57733: 29.0.50; Fix "Invalid search bound (wrong side of point)" error in replace-*-in-region In-Reply-To: <87illtbzyn.fsf@gmail.com> (=?utf-8?Q?=22K=C3=A9vin?= Le Gouguec"'s message of "Sun, 11 Sep 2022 19:09:04 +0200") References: <87r10hc35z.fsf@gmail.com> <87illtdgxe.fsf@gnus.org> <87illtbzyn.fsf@gmail.com> X-Now-Playing: Orbital's _Thirty-Something (1)_: "Impact (30 Year Later And The Earth Is Still Burning Mix)" Date: Sun, 11 Sep 2022 19:55:14 +0200 Message-ID: <87edwhdce5.fsf@gnus.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: Kévin Le Gouguec writes: > That makes a lot of sense, thanks; new patch attached. Thanks; pushed to Emacs 29. Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 57733 Cc: 57733@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) K=C3=A9vin Le Gouguec writes: > That makes a lot of sense, thanks; new patch attached. Thanks; pushed to Emacs 29. From debbugs-submit-bounces@debbugs.gnu.org Sun Sep 11 13:55:36 2022 Received: (at control) by debbugs.gnu.org; 11 Sep 2022 17:55:36 +0000 Received: from localhost ([127.0.0.1]:43345 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oXRBA-0007Ew-Ag for submit@debbugs.gnu.org; Sun, 11 Sep 2022 13:55:36 -0400 Received: from quimby.gnus.org ([95.216.78.240]:42992) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1oXRB8-0007Ej-8n for control@debbugs.gnu.org; Sun, 11 Sep 2022 13:55:34 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnus.org; s=20200322; h=Subject:From:To:Message-Id:Date:Sender:Reply-To:Cc: MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=ImqBqHy6ikg2dKmsZfWBfggs/EhVvO9+b8lVxU8bl/Y=; b=szy62pnyns4XxIN/UlkTEI8lJt OVIGDLKq1ebELPXuImBs1owBGQiu5b2lfM2yXEIXS7RUxCV76jniVOJdJLEUMeIK3zUkJgY2j5AG2 Lh9+VhWT9ZOP/qCOLSEDcCvLrQ0pFHxFHdNHDoSw3OD7qRgkISMua4xAI5IaKeK/dlPg=; Received: from [84.212.220.105] (helo=joga) by quimby.gnus.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oXRB0-0006md-Bz for control@debbugs.gnu.org; Sun, 11 Sep 2022 19:55:28 +0200 Date: Sun, 11 Sep 2022 19:55:25 +0200 Message-Id: <87czc1dcdu.fsf@gnus.org> To: control@debbugs.gnu.org From: Lars Ingebrigtsen Subject: control message for bug #57733 X-Spam-Report: Spam detection software, running on the system "quimby.gnus.org", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see @@CONTACT_ADDRESS@@ for details. Content preview: close 57733 29.1 quit Content analysis details: (-2.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: control X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) close 57733 29.1 quit From unknown Fri Aug 15 14:18:31 2025 Received: (at fakecontrol) by fakecontrolmessage; To: internal_control@debbugs.gnu.org From: Debbugs Internal Request Subject: Internal Control Message-Id: bug archived. Date: Mon, 10 Oct 2022 11:24:09 +0000 User-Agent: Fakemail v42.6.9 # This is a fake control message. # # The action: # bug archived. thanks # This fakemail brought to you by your local debbugs # administrator