Skip to content

Commit 0a9f4c5

Browse files
committed
fix: loading utf-8 file when locale encoding is set to ascii
Configurator-pg fails to load UTF-8 encoded files when the locale settings are set to ASCII chars. This commit fixes this by using a safer and faster UTF-8 decoding when reading files. See: PostgREST/postgrest#4386 (comment) for more info on this. Signed-off-by: Taimoor Zaeem <taimoorzaeem@gmail.com>
1 parent c9ebf82 commit 0a9f4c5

7 files changed

Lines changed: 27 additions & 2 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Revision history for configurator-pg
22

3+
# Unreleased
4+
5+
* Fix loading `utf-8` file when locale encoding is set to `ASCII`
6+
37
## 0.2.10 -- 2024-03-06
48

59
* Allow megaparsec-9.6

‎configurator-pg.cabal‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ library
3434
Data.Configurator.Syntax
3535
Data.Configurator.Types
3636
build-depends: base >= 4.9 && < 4.22
37+
, bytestring >= 0.10.8 && < 0.13
3738
, megaparsec >= 7.0.0 && < 9.8
3839
, containers >= 0.5.6.2 && < 0.8
3940
, protolude >= 0.1.10 && < 0.4

‎src/Data/Configurator/Load.hs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import Protolude
66

77
import Control.Exception (throw)
88
import Text.Megaparsec (parse, errorBundlePretty)
9+
import qualified Data.ByteString as BS
910
import qualified Data.Map.Strict as M
1011
import Data.Scientific (toBoundedInteger,
1112
toRealFloat)
1213
import qualified Data.Text as T
14+
import qualified Data.Text.Encoding as T
1315
import qualified Data.Text.Lazy as TL
1416
import Data.Text.Lazy.Builder (fromString,
1517
fromText,
@@ -31,7 +33,7 @@ load path = applyDirective "" "" M.empty (Import $ T.pack path)
3133

3234
loadOne :: Path -> IO [Directive]
3335
loadOne path = do
34-
s <- readFile (T.unpack path)
36+
s <- T.decodeUtf8 <$> BS.readFile (T.unpack path)
3537
case parse topLevel (T.unpack path) s of
3638
Left err -> throw $ ParseError $ T.pack $ errorBundlePretty err
3739
Right directives -> return directives

‎tests/Test.hs‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
{-# LANGUAGE OverloadedStrings #-}
22
{-# LANGUAGE ScopedTypeVariables #-}
3+
{-# LANGUAGE CPP #-}
34

45
module Main where
56

67
import Protolude hiding (bool, list, optional)
78

89
import Data.Configurator
910
import qualified Data.Text as T
11+
import qualified GHC.IO.Encoding as E
12+
import qualified GHC.IO.Encoding.Latin1 as E
1013
import System.Environment
1114
import System.FilePath
1215
import Test.Framework
@@ -20,6 +23,7 @@ tests :: [Test]
2023
tests =
2124
[ testCase "read-simple" $ readTest "simple.cfg"
2225
, testCase "read-pathological" $ readTest "pathological.cfg"
26+
, testCase "read-utf-8-with-ascii-locale" $ readTestWithLocale "utf-8.cfg" E.ascii
2327
, testCase "load" loadTest
2428
, testCase "load" loadTest
2529
, testCase "types" typesTest
@@ -51,6 +55,9 @@ testFile name = "tests" </> "resources" </> name
5155
errorFile :: FilePath -> FilePath
5256
errorFile name = testFile name <> ".err"
5357

58+
errorFileGHC8 :: FilePath -> FilePath
59+
errorFileGHC8 name = testFile name <> ".err.ghc8"
60+
5461
parse :: Config -> Parser Value a -> Key -> Either Text a
5562
parse cfg p key = runParser (required key p) cfg
5663

@@ -63,6 +70,10 @@ parseSub cfg p prefix = runParser (subassocs prefix p) cfg
6370
readTest :: FilePath -> Assertion
6471
readTest file = load (testFile file) >> return ()
6572

73+
readTestWithLocale :: FilePath -> E.TextEncoding -> Assertion
74+
readTestWithLocale file locale =
75+
E.setLocaleEncoding locale >> load (testFile file) >> return ()
76+
6677
loadTest :: Assertion
6778
loadTest =
6879
withLoad "pathological.cfg" $ \cfg -> do
@@ -233,7 +244,11 @@ parseErrorTest file = do
233244

234245
ioErrorTest :: FilePath -> Assertion
235246
ioErrorTest file = do
247+
#if __GLASGOW_HASKELL__ >= 900
236248
err <- readFile $ errorFile file
249+
#else
250+
err <- readFile $ errorFileGHC8 file
251+
#endif
237252
(load (testFile file) >> assertFailure "expected an IO error")
238253
`catch` \ (ex :: IOException) -> do
239254
assertEqual "" err (show ex)

‎tests/resources/err-import.cfg.err‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
tests/resources/not-exist.cfg: openFile: does not exist (No such file or directory)
1+
tests/resources/not-exist.cfg: withBinaryFile: does not exist (No such file or directory)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
tests/resources/not-exist.cfg: openBinaryFile: does not exist (No such file or directory)

‎tests/resources/utf-8.cfg‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Commènt utf-8 chàrs
2+
utf-kèy = "utf-8-vàlue"

0 commit comments

Comments
 (0)