From b12aada52d682c45aa1e66e13dc448dc894aee79 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Thu, 1 Oct 2026 10:31:51 +0200 Subject: fix: double a quote in a search term, as notmuch expects SearchTerm::quote() escaped an embedded double quote with a backslash. notmuch has no backslash escape inside a quoted term: it doubles the quote, and a backslash-escaped one ENDS the term. Selected text holding a quote therefore let the rest of the selection reach the query as syntax. Measured on a throwaway index: under a `tag:nomatch and` scope, the backslash form of `x " or tag:inbox or id:"` matched every message, while the doubled form matched none. quote() now doubles the quote and leaves a backslash alone, since notmuch reads it literally. Truncation still runs first, so a cut cannot split a doubled pair. Co-Authored-By: Claude Opus 5.5 --- tests/test_searchterm.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'tests/test_searchterm.cpp') diff --git a/tests/test_searchterm.cpp b/tests/test_searchterm.cpp index 53185f3..7a0dfd7 100644 --- a/tests/test_searchterm.cpp +++ b/tests/test_searchterm.cpp @@ -56,9 +56,13 @@ void TestSearchTerm::escapesEmbeddedQuotes() { // A selection is arbitrary prose and can carry a quote. Unescaped, it ends // the quoted string early and the rest becomes stray query syntax, which - // notmuch accepts and matches nothing on. + // notmuch accepts and matches nothing on. notmuch DOUBLES a quote; a + // backslash-escaped one ends the term and lets the rest escape the query. QCOMPARE(SearchTerm::quote(QStringLiteral("say \"hello\" now")), - QStringLiteral("\"say \\\"hello\\\" now\"")); + QStringLiteral("\"say \"\"hello\"\" now\"")); + // A backslash is literal to notmuch and must reach it unchanged. + QCOMPARE(SearchTerm::quote(QStringLiteral("x \\\" or tag:inbox")), + QStringLiteral("\"x \\\"\" or tag:inbox\"")); } void TestSearchTerm::collapsesWhitespaceAndNewlines() -- cgit v1.2.3