@@ -403,12 +403,15 @@ chunkedSource ipair = do
403403 (src, mlen) <- liftIO $ I.readIORef ipair
404404 go src mlen
405405 where
406− go src NeedLen = do
407− (src', len) <- lift $ src C.$$+ getLen
408− go src' $ HaveLen len
409− go src NeedLenNewline = do
410− (src', len) <- lift $ src C.$$+ (CB.take 2 >> getLen)
411− go src' $ HaveLen len
406+ go' src front = do
407+ (src', (len, bs)) <- lift $ src C.$$+ front getLen
408+ let src''
409+ | S.null bs = src'
410+ | otherwise = C.yield bs >> src'
411+ go src'' $ HaveLen len
412+
413+ go src NeedLen = go' src id
414+ go src NeedLenNewline = go' src (CB.take 2 >>)
412415 go src (HaveLen 0) = liftIO $ I.writeIORef ipair (src, HaveLen 0)
413416 go src (HaveLen len) = do
414417 (src', mbs) <- lift $ src C.$$+ CL.head
@@ -430,14 +433,25 @@ chunkedSource ipair = do
430433 C.yield bs
431434 go src mlen
432435
433− getLen :: MonadIO m => C.Sink ByteString m Word
436+ getLen :: Monad m => C.Sink ByteString m (Word, ByteString)
434437 getLen = do
435− bss <- CB.takeWhile (/= 10) C.=$ CL.consume -- FIXME avoid attack
436− _ <- CB.take 1
437− return $
438− S.foldl' (\i c -> i * 16 + fromIntegral (hexToWord c)) 0
439− $ B.takeWhile isHexDigit
440− $ B.concat bss
438+ mbs <- CL.head
439+ case mbs of
440+ Nothing -> return (0, S.empty)
441+ Just bs -> do
442+ (x, y) <-
443+ case S.breakByte 10 bs of
444+ (x, y)
445+ | S.null y -> do
446+ mbs2 <- CL.head
447+ case mbs2 of
448+ Nothing -> return (x, y)
449+ Just bs2 -> return $ S.breakByte 10 $ bs `S.append` bs2
450+ | otherwise -> return (x, y)
451+ let w =
452+ S.foldl' (\i c -> i * 16 + fromIntegral (hexToWord c)) 0
453+ $ B.takeWhile isHexDigit x
454+ return (w, S.drop 1 y)
441455
442456 hexToWord w
443457 | w < 58 = w - 48