From 9a5d54c0351e071a962d8d92805e0edf2f95fa1b Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Thu, 19 Dec 2019 06:59:27 +0100 Subject: [PATCH] Escape non-source characters in the encoder --- CHANGELOG.md | 1 + src/Language/GraphQL/AST/Encoder.hs | 20 +++++++++++++------- tests/Language/GraphQL/AST/EncoderSpec.hs | 2 ++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cc152c..fed2d47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file. - Fragment spread is evaluated based on the `__typename` resolver. If the resolver is missing, it is assumed that the type condition is satisfied (all fragments are included). +- Escaping characters during encoding. ### Added - Directive support (@skip and @include). diff --git a/src/Language/GraphQL/AST/Encoder.hs b/src/Language/GraphQL/AST/Encoder.hs index afc425f..056ae2c 100644 --- a/src/Language/GraphQL/AST/Encoder.hs +++ b/src/Language/GraphQL/AST/Encoder.hs @@ -18,6 +18,7 @@ import Data.Monoid ((<>)) import qualified Data.List.NonEmpty as NonEmpty (toList) import Data.Text.Lazy (Text) import qualified Data.Text.Lazy as Text.Lazy +import qualified Data.Text.Lazy.Builder as Builder import Data.Text.Lazy.Builder (toLazyText) import Data.Text.Lazy.Builder.Int (decimal) import Data.Text.Lazy.Builder.RealFloat (realFloat) @@ -191,10 +192,18 @@ booleanValue True = "true" booleanValue False = "false" stringValue :: Text -> Text -stringValue - = quotes - . Text.Lazy.replace "\"" "\\\"" - . Text.Lazy.replace "\\" "\\\\" +stringValue string = Builder.toLazyText + $ quote + <> Text.Lazy.foldr replace quote string + where + replace '\\' = mappend $ Builder.fromLazyText "\\\\" + replace '\"' = mappend $ Builder.fromLazyText "\\\"" + replace '\b' = mappend $ Builder.fromLazyText "\\b" + replace '\f' = mappend $ Builder.fromLazyText "\\f" + replace '\n' = mappend $ Builder.fromLazyText "\\n" + replace '\r' = mappend $ Builder.fromLazyText "\\r" + replace char = mappend $ Builder.singleton char + quote = Builder.singleton '\"' listValue :: Formatter -> [Full.Value] -> Text listValue formatter = bracketsCommas formatter $ value formatter @@ -243,9 +252,6 @@ brackets = between '[' ']' braces :: Text -> Text braces = between '{' '}' -quotes :: Text -> Text -quotes = between '"' '"' - spaces :: forall a. (a -> Text) -> [a] -> Text spaces f = Text.Lazy.intercalate "\SP" . fmap f diff --git a/tests/Language/GraphQL/AST/EncoderSpec.hs b/tests/Language/GraphQL/AST/EncoderSpec.hs index a418a61..acf8075 100644 --- a/tests/Language/GraphQL/AST/EncoderSpec.hs +++ b/tests/Language/GraphQL/AST/EncoderSpec.hs @@ -17,3 +17,5 @@ spec = describe "value" $ do value minified (String "\\") `shouldBe` "\"\\\\\"" it "escapes quotes" $ value minified (String "\"") `shouldBe` "\"\\\"\"" + it "escapes backspace" $ + value minified (String "a\bc") `shouldBe` "\"a\\bc\""