Commits

Bryan O'Sullivan committed 792a867 Merge

Merge branch 'basvandijk-fix-DoS'

  • Participants
  • Parent commits b44e92b, 0a2db3f

Comments (0)

Files changed (3)

File Data/Attoparsec/ByteString/Char8.hs

 import Data.ByteString.Internal (c2w, w2c)
 import Data.Int (Int8, Int16, Int32, Int64)
 import Data.String (IsString(..))
-import Data.Scientific (Scientific, coefficient, base10Exponent)
-import qualified Data.Scientific as Sci (scientific)
+import Data.Scientific (Scientific)
+import qualified Data.Scientific as Sci
 import Data.Word (Word8, Word16, Word32, Word64, Word)
 import Prelude hiding (takeWhile)
 import qualified Data.Attoparsec.ByteString as A
 -- This function does not accept string representations of \"NaN\" or
 -- \"Infinity\".
 double :: Parser Double
-double = rational
+double = scientifically Sci.toRealFloat
 
 -- | Parse a number, attempting to preserve both speed and precision.
 --
 -- \"
 number :: Parser Number
 number = scientifically $ \s ->
-            let e = base10Exponent s
-                c = coefficient s
+            let e = Sci.base10Exponent s
+                c = Sci.coefficient s
             in if e >= 0
                then I (c * 10 ^ e)
-               else D (fromInteger c / 10 ^ negate e)
+               else D (Sci.toRealFloat s)
 
 -- | Parse a scientific number.
 --
 scientific :: Parser Scientific
 scientific = scientifically id
 
+-- A strict pair
+data SP = SP !Integer {-# UNPACK #-}!Int
+
 {-# INLINE scientifically #-}
 scientifically :: (Scientific -> a) -> Parser a
 scientifically h = do
 
   n <- decimal
 
-  let f fracDigits = Sci.scientific (B8.foldl' step n fracDigits)
-                                    (negate $ B8.length fracDigits)
+  let f fracDigits = SP (B8.foldl' step n fracDigits)
+                        (negate $ B8.length fracDigits)
       step a w = a * 10 + fromIntegral (w - 48)
 
   dotty <- I.peekWord8
   -- '.' -> ascii 46
-  s <- case dotty of
-         Just 46 -> I.anyWord8 *> (f <$> I.takeWhile isDigit_w8)
-         _       -> pure (Sci.scientific n 0)
+  SP c e <- case dotty of
+              Just 46 -> I.anyWord8 *> (f <$> I.takeWhile isDigit_w8)
+              _       -> pure (SP n 0)
 
-  let !signedCoeff | positive  =          coefficient s
-                   | otherwise = negate $ coefficient s
+  let !signedCoeff | positive  =  c
+                   | otherwise = -c
 
   let littleE = 101
       bigE    = 69
-  (I.satisfy (\c -> c == littleE || c == bigE) *>
-      fmap (h . Sci.scientific signedCoeff . (base10Exponent s +)) (signed decimal)) <|>
-    return (h $ Sci.scientific signedCoeff   (base10Exponent s))
+  (I.satisfy (\ex -> ex == littleE || ex == bigE) *>
+      fmap (h . Sci.scientific signedCoeff . (e +)) (signed decimal)) <|>
+    return (h $ Sci.scientific signedCoeff    e)

File Data/Attoparsec/Text.hs

 import Control.Applicative (pure, (<$>), (*>), (<*), (<|>))
 import Data.Attoparsec.Combinator
 import Data.Attoparsec.Number (Number(..))
-import Data.Scientific (Scientific, coefficient, base10Exponent)
-import qualified Data.Scientific as Sci (scientific)
+import Data.Scientific (Scientific)
+import qualified Data.Scientific as Sci
 import Data.Attoparsec.Text.Internal (Parser, Result, parse, takeWhile1)
 import Data.Bits (Bits, (.|.), shiftL)
 import Data.Char (isAlpha, isDigit, isSpace, ord)
 -- This function does not accept string representations of \"NaN\" or
 -- \"Infinity\".
 double :: Parser Double
-double = rational
+double = scientifically Sci.toRealFloat
 
 -- | Parse a number, attempting to preserve both speed and precision.
 --
 -- \"Infinity\".
 number :: Parser Number
 number = scientifically $ \s ->
-            let e = base10Exponent s
-                c = coefficient s
+            let e = Sci.base10Exponent s
+                c = Sci.coefficient s
             in if e >= 0
                then I (c * 10 ^ e)
-               else D (fromInteger c / 10 ^ negate e)
+               else D (Sci.toRealFloat s)
 
 -- | Parse a scientific number.
 --
 scientific :: Parser Scientific
 scientific = scientifically id
 
+-- A strict pair
+data SP = SP !Integer {-# UNPACK #-}!Int
+
 {-# INLINE scientifically #-}
 scientifically :: (Scientific -> a) -> Parser a
 scientifically h = do
 
   n <- decimal
 
-  let f fracDigits = Sci.scientific (T.foldl' step n fracDigits)
-                                    (negate $ T.length fracDigits)
+  let f fracDigits = SP (T.foldl' step n fracDigits)
+                        (negate $ T.length fracDigits)
       step a c = a * 10 + fromIntegral (ord c - 48)
 
-  s <- (I.satisfy (=='.') *> (f <$> I.takeWhile isDigit)) <|>
-         pure (Sci.scientific n 0)
+  SP c e <- (I.satisfy (=='.') *> (f <$> I.takeWhile isDigit)) <|>
+            pure (SP n 0)
 
-  let !signedCoeff | positive  =          coefficient s
-                   | otherwise = negate $ coefficient s
+  let !signedCoeff | positive  =  c
+                   | otherwise = -c
 
-  (I.satisfy (\c -> c == 'e' || c == 'E') *>
-      fmap (h . Sci.scientific signedCoeff . (base10Exponent s +)) (signed decimal)) <|>
-    return (h $ Sci.scientific signedCoeff   (base10Exponent s))
+  (I.satisfy (\w -> w == 'e' || w == 'E') *>
+      fmap (h . Sci.scientific signedCoeff . (e +)) (signed decimal)) <|>
+    return (h $ Sci.scientific signedCoeff    e)
 
 -- | Parse a single digit, as recognised by 'isDigit'.
 digit :: Parser Char

File attoparsec.cabal

                  containers,
                  deepseq,
                  text >= 0.11.3.1,
-                 scientific >= 0.2 && < 0.3
+                 scientific >= 0.3.1
 
   exposed-modules: Data.Attoparsec
                    Data.Attoparsec.ByteString