on master help sign in
Reject numbers that contain leading zeros (gh-480)

This is forbidden by RFC 7159, probably because a JS engine may interpret such a number as octal (!!!). This bug was exposed by JSONTestSuite. Hooray JSONTestSuite!

commit3fb7c155f2255482b1b9566ec5c1eaf9895d630e authorBryan O'Sullivan <bryano@fb.com> dateFri 28 Oct 2016, 15:09 (10 years ago) parentb87d021
2 files changed+11−2
Data/Aeson/Parser/Internal.hs+11−1 tests/UnitTests.hs−1
Data/Aeson/Parser/Internal.hs+11−1
@@ -46,6 +46,7 @@ import Data.Vector as Vector (Vector, empty, fromListN, reverse)
4646import qualified Data.Attoparsec.ByteString as A
4747import qualified Data.Attoparsec.Lazy as L
4848import qualified Data.ByteString as B
49+import qualified Data.ByteString.Unsafe as B
4950import qualified Data.ByteString.Lazy as L
5051import qualified Data.HashMap.Strict as H
5152import qualified Data.Scientific as Sci
@@ -299,6 +300,15 @@ jsonEOF' = json' <* skipSpace <* endOfInput
299300-- A strict pair
300301data SP = SP !Integer {-# UNPACK #-}!Int
301302
303+decimal0 :: Parser Integer
304+decimal0 = do
305+ let step a w = a * 10 + fromIntegral (w - zero)
306+ zero = 48
307+ digits <- A.takeWhile1 isDigit_w8
308+ if B.length digits > 1 && B.unsafeHead digits == zero
309+ then fail "leading zero"
310+ else return (B.foldl' step 0 digits)
311+
302312{-# INLINE scientific #-}
303313scientific :: Parser Scientific
304314scientific = do
@@ -309,7 +319,7 @@ scientific = do
309319 when (sign == plus || sign == minus) $
310320 void A.anyWord8
311321
312− n <- decimal
322+ n <- decimal0
313323
314324 let f fracDigits = SP (B.foldl' step n fracDigits)
315325 (negate $ B.length fracDigits)
tests/UnitTests.hs−1
@@ -667,7 +667,6 @@ _blacklist = HashSet.fromList [
667667 , "i_string_not_in_unicode_range.json"
668668 , "i_string_truncated-utf-8.json"
669669 , "i_structure_UTF-8_BOM_empty_object.json"
670− , "n_number_-01.json"
671670 , "n_number_-2..json"
672671 , "n_number_0.e1.json"
673672 , "n_number_2.e+3.json"