Revert "fix:lib:Hledger.Query: words'': Parse escaped quotes in quoted patterns" [#2513]

This reverts commit de900e5b24, it's not
as safe as we thought.
This commit is contained in:
Simon Michael 2026-01-06 21:55:35 -10:00
parent 98fdffd516
commit 3c0a02a34a

View File

@ -86,7 +86,7 @@ import Data.Text (Text)
import Data.Text qualified as T
import Data.Time.Calendar (Day, fromGregorian )
import Safe (headErr, readMay, maximumByMay, maximumMay, minimumMay)
import Text.Megaparsec (between, noneOf, sepBy, try, (<?>), notFollowedBy, anySingle)
import Text.Megaparsec (between, noneOf, sepBy, try, (<?>), notFollowedBy)
import Text.Megaparsec.Char (char, string, string')
@ -241,21 +241,13 @@ words'' prefixes = fromparse . parsewith maybePrefixedQuotedPhrases -- XXX
prefix = not' <> next
p <- singleQuotedPattern <|> doubleQuotedPattern
return $ prefix <> stripquotes p
singleQuotedPattern :: SimpleTextParser T.Text
singleQuotedPattern = stripquotes . T.pack <$> between (char '\'') (char '\'') (many $ noneOf ("'" :: [Char]))
doubleQuotedPattern :: SimpleTextParser T.Text
doubleQuotedPattern = stripquotes . T.pack <$> between (char '"') (char '"') (many $ noneOf ("\"" :: [Char]))
patterns :: SimpleTextParser T.Text
patterns = T.pack <$> many (noneOf (" \n\r" :: [Char]))
singleQuotedPattern :: SimpleTextParser T.Text
singleQuotedPattern = quotedPattern '\''
doubleQuotedPattern :: SimpleTextParser T.Text
doubleQuotedPattern = quotedPattern '"'
quotedPattern :: Char -> SimpleTextParser T.Text
quotedPattern quote = stripquotes . T.pack <$> between (char quote) (char quote) (many $ escapedChar <|> noneOf [quote])
where
escapedChar :: SimpleTextParser Char
escapedChar = char '\\' >> anySingle
-- XXX
-- keep synced with patterns below, excluding "not"
queryprefixes :: [T.Text]
@ -433,8 +425,8 @@ parseBooleanQuery d t =
-- if it is not one of the keywords "not", "and", "or".
queryArgP :: SimpleTextParser T.Text
queryArgP = choice'
[ singleQuotedPattern,
doubleQuotedPattern,
[ stripquotes . T.pack <$> between (char '\'') (char '\'') (many $ noneOf ("'" :: [Char])),
stripquotes . T.pack <$> between (char '"') (char '"') (many $ noneOf ("\"" :: [Char])),
T.pack <$> (notFollowedBy keywordP >> (many $ noneOf (") \n\r" :: [Char]))) ]
where
@ -1060,9 +1052,7 @@ tests_Query = testGroup "Query" [
,testCase "parseBooleanQuery" $ do
parseBooleanQuery nulldate "(tag:'atag=a')" @?= Right (Tag (toRegexCI' "atag") (Just $ toRegexCI' "a"), [])
parseBooleanQuery nulldate "(tag:'atag=\\'a')" @?= Right (Tag (toRegexCI' "atag") (Just $ toRegexCI' "'a"), [])
parseBooleanQuery nulldate "( tag:\"atag=a\" )" @?= Right (Tag (toRegexCI' "atag") (Just $ toRegexCI' "a"), [])
parseBooleanQuery nulldate "(tag:\"atag=\\\"a\")" @?= Right (Tag (toRegexCI' "atag") (Just $ toRegexCI' "\"a"), [])
parseBooleanQuery nulldate "(acct:'expenses:food')" @?= Right (Acct $ toRegexCI' "expenses:food", [])
parseBooleanQuery nulldate "(((acct:'expenses:food')))" @?= Right (Acct $ toRegexCI' "expenses:food", [])
parseBooleanQuery nulldate "acct:'expenses:food' AND desc:'b'" @?= Right (And [Acct $ toRegexCI' "expenses:food", Desc $ toRegexCI' "b"], [])
@ -1089,9 +1079,6 @@ tests_Query = testGroup "Query" [
(words'' ["desc:"] "not:desc:'a b'") @?= ["not:desc:a b"]
(words'' queryprefixes "\"acct:expenses:autres d\233penses\"") @?= ["acct:expenses:autres d\233penses"]
(words'' queryprefixes "\"") @?= ["\""]
(words'' [] "\"a\\\"a\\\"\"") @?= ["a\"a\""]
(words'' [] "'\\'a'") @?= ["'a"]
,testCase "filterQuery" $ do
filterQuery queryIsDepth Any @?= Any