on master help sign in
Merge pull request #564 from hce/fix-headerlength-check
72f3066Michael Snoyman
wai-extra/ChangeLog.md+4
@@ -1,3 +1,7 @@
1+## 3.0.16.1
2+
3+* Fix the way the header length is checked (for limiting the max header length)
4+
1## 3.0.16.0
5## 3.0.16.0
2
6
3* Add a new function "parseRequestBodyEx" that allows various size limits to be set.
7* Add a new function "parseRequestBodyEx" that allows various size limits to be set.
wai-extra/Network/Wai/Parse.hs+8−3
@@ -425,7 +425,7 @@ takeLine maxlen src =
425 go front = do
425 go front = do
426 bs <- readSource src
426 bs <- readSource src
427 case maxlen of
427 case maxlen of
428− Just maxlen' -> when (S.length front + S.length bs > maxlen') $
428+ Just maxlen' -> when (S.length front > maxlen') $
429 error "Header line length exceeds allowed maximum."
429 error "Header line length exceeds allowed maximum."
430 Nothing -> return ()
430 Nothing -> return ()
431 if S.null bs
431 if S.null bs
@@ -439,7 +439,12 @@ takeLine maxlen src =
439 then go $ front `S.append` x
439 then go $ front `S.append` x
440 else do
440 else do
441 when (S.length y > 1) $ leftover src $ S.drop 1 y
441 when (S.length y > 1) $ leftover src $ S.drop 1 y
442− return $ Just $ killCR $ front `S.append` x
442+ let res = front `S.append` x
443+ case maxlen of
444+ Just maxlen' -> when (S.length res > maxlen') $
445+ error "Header line length exceeds allowed maximum."
446+ Nothing -> return ()
447+ return $ Just $ killCR $ res
443
448
444takeLines' :: Maybe Int -> Maybe Int -> Source -> IO [S.ByteString]
449takeLines' :: Maybe Int -> Maybe Int -> Source -> IO [S.ByteString]
445takeLines' lineLength maxLines source =
450takeLines' lineLength maxLines source =
@@ -634,7 +639,7 @@ wrapTillBound bound src max' = do
634 return $ front bs
639 return $ front bs
635 else push $ front bs
640 else push $ front bs
636 where
641 where
637− push bs =
642+ push bs = do
638 case findBound bound bs of
643 case findBound bound bs of
639 FoundBound before after -> do
644 FoundBound before after -> do
640 let before' = killCRLF before
645 let before' = killCRLF before
wai-extra/test/Network/Wai/ParseSpec.hs+15−14
@@ -104,38 +104,38 @@ caseParseRequestBody = do
104 result3' `shouldBe` expected3
104 result3' `shouldBe` expected3
105
105
106 it "parsing with memory limit" $ do
106 it "parsing with memory limit" $ do
107− SRequest req4 bod4 <- toRequest'' ctype3 content3
107+ SRequest req4 _bod4 <- toRequest'' ctype3 content3
108 result4' <- parseRequestBodyEx ( setMaxRequestNumFiles 1 $ setMaxRequestKeyLength 14 def ) lbsBackEnd req4
108 result4' <- parseRequestBodyEx ( setMaxRequestNumFiles 1 $ setMaxRequestKeyLength 14 def ) lbsBackEnd req4
109 result4' `shouldBe` expected3
109 result4' `shouldBe` expected3
110
110
111 it "exceeding number of files" $ do
111 it "exceeding number of files" $ do
112− SRequest req4 bod4 <- toRequest'' ctype3 content3
112+ SRequest req4 _bod4 <- toRequest'' ctype3 content3
113 (parseRequestBodyEx ( setMaxRequestNumFiles 0 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
113 (parseRequestBodyEx ( setMaxRequestNumFiles 0 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
114
114
115 it "exceeding parameter length" $ do
115 it "exceeding parameter length" $ do
116− SRequest req4 bod4 <- toRequest'' ctype3 content3
116+ SRequest req4 _bod4 <- toRequest'' ctype3 content3
117 (parseRequestBodyEx ( setMaxRequestKeyLength 2 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
117 (parseRequestBodyEx ( setMaxRequestKeyLength 2 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
118
118
119 it "exceeding file size" $ do
119 it "exceeding file size" $ do
120− SRequest req4 bod4 <- toRequest'' ctype3 content3
120+ SRequest req4 _bod4 <- toRequest'' ctype3 content3
121 (parseRequestBodyEx ( setMaxRequestFileSize 2 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
121 (parseRequestBodyEx ( setMaxRequestFileSize 2 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
122
122
123 it "exceeding total file size" $ do
123 it "exceeding total file size" $ do
124− SRequest req4 bod4 <- toRequest'' ctype3 content3
124+ SRequest req4 _bod4 <- toRequest'' ctype3 content3
125 (parseRequestBodyEx ( setMaxRequestFilesSize 20 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
125 (parseRequestBodyEx ( setMaxRequestFilesSize 20 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
126− SRequest req5 bod5 <- toRequest'' ctype3 content5
126+ SRequest req5 _bod5 <- toRequest'' ctype3 content5
127 (parseRequestBodyEx ( setMaxRequestFilesSize 20 def ) lbsBackEnd req5) `shouldThrow` anyErrorCall
127 (parseRequestBodyEx ( setMaxRequestFilesSize 20 def ) lbsBackEnd req5) `shouldThrow` anyErrorCall
128
128
129 it "exceeding max parm value size" $ do
129 it "exceeding max parm value size" $ do
130− SRequest req4 bod4 <- toRequest'' ctype2 content2
130+ SRequest req4 _bod4 <- toRequest'' ctype2 content2
131 (parseRequestBodyEx ( setMaxRequestParmsSize 10 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
131 (parseRequestBodyEx ( setMaxRequestParmsSize 10 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
132
132
133 it "exceeding max header lines" $ do
133 it "exceeding max header lines" $ do
134− SRequest req4 bod4 <- toRequest'' ctype2 content2
134+ SRequest req4 _bod4 <- toRequest'' ctype2 content2
135 (parseRequestBodyEx ( setMaxHeaderLines 1 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
135 (parseRequestBodyEx ( setMaxHeaderLines 1 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
136
136
137 it "exceeding header line size" $ do
137 it "exceeding header line size" $ do
138− SRequest req4 bod4 <- toRequest'' ctype2 content4
138+ SRequest req4 _bod4 <- toRequest'' ctype3 content4
139 (parseRequestBodyEx ( setMaxHeaderLineLength 8190 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
139 (parseRequestBodyEx ( setMaxHeaderLineLength 8190 def ) lbsBackEnd req4) `shouldThrow` anyErrorCall
140
140
141 it "Testing parseRequestBodyEx with application/x-www-form-urlencoded" $ do
141 it "Testing parseRequestBodyEx with application/x-www-form-urlencoded" $ do
@@ -177,13 +177,14 @@ caseParseRequestBody = do
177 <> "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh--\r\n"
177 <> "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh--\r\n"
178 content4 =
178 content4 =
179 "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh\r\n"
179 "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh\r\n"
180− <> "Content-Disposition: form-data; name=\"yaml\"; filename=\"README\"\r\n"
180+ <> "Content-Disposition: form-data; name=\"alb\"; filename=\"README\"\r\n"
181 <> "Content-Type: application/octet-stream\r\n\r\n"
181 <> "Content-Type: application/octet-stream\r\n\r\n"
182− <> "Photo blog using Hack.\n\r\n"
182+ <> "Photo blog using Hack.\r\n\r\n"
183 <> "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh\r\n"
183 <> "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh\r\n"
184− <> "Content-Disposition: form-data; name=\"bla\"; filename=\"riedmie\"\r\n"
184+ <> "Content-Disposition: form-data; name=\"bla\"; filename=\"riedmi"
185+ <> S8.replicate 8190 'e' <> "\"\r\n"
185− <> "Content-Type: application/octet-stream=TOOLONG=" <> S8.replicate 8192 '=' <> "\r\n\r\n"
186+ <> "Content-Type: application/octet-stream\r\n\r\n"
186− <> "Photo blog using Hack.\n\r\n"
187+ <> "Photo blog using Hack.\r\n\r\n"
187 <> "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh--\r\n"
188 <> "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh--\r\n"
188 content5 =
189 content5 =
189 "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh\r\n"
190 "------WebKitFormBoundaryB1pWXPZ6lNr8RiLh\r\n"
wai-extra/wai-extra.cabal+1−1
@@ -1,5 +1,5 @@
1Name: wai-extra
1Name: wai-extra
2−Version: 3.0.16.0
2+Version: 3.0.16.1
3Synopsis: Provides some basic WAI handlers and middleware.
3Synopsis: Provides some basic WAI handlers and middleware.
4description:
4description:
5 Provides basic WAI handler and middleware functionality:
5 Provides basic WAI handler and middleware functionality: