Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wrapTillBound in Network/Wai/Parse.hs incorrectly counting max chunk size (e.g. file sizes towards max parameter size) #1000

Open
moll opened this issue Aug 25, 2024 · 0 comments

Comments

@moll
Copy link

moll commented Aug 25, 2024

Hey, all!

Thanks for maintaining Wai and the related modules!

I'm seeing some odd behavior where Wai Parse throws PayloadTooLarge when it shouldn't. That is, it seems to be counting multipart file parts' sizes towards the max parameter size (prboMaxParmsSize).

Reading the code, I suspect this is due to

go ref sref = do
state <- readIORef ref
case state of
WTBDone _ -> return S.empty
WTBWorking front -> do
bs <- readSource src
cur <- atomicModifyIORef' sref $ \cur ->
let new = cur + fromIntegral (S.length bs) in (new, new)
case max' of
Just max'' | cur > max'' -> E.throwIO PayloadTooLarge
_ -> return ()
if S.null bs
then do
writeIORef ref $ WTBDone False
return $ front bs
else push $ front bs
, where it reads a chunk and checks its size before looking for a boundary. It's only in the push function where boundary seeking happens. If a multipart requests comes in with a non-file parameter first and the entire read chunk is larger than the permitted parms size, it errors out, even if the particular parameter its reading is well below the permitted size. The same should technically happen backwards, too --- file first, param later. In other words, the size check should happen after a boundary is found.

If I'm correct, I suppose this hasn't come up in the years before due to the default max params size (64kB) being larger than a read chunk in production situations. Even I initially saw this in tests, where I suspect the Network.Wai.Test module jams the entire body into one chunk somehow. In non-test settings I tracked it down by setting the max parameters size to small numbers (e.g. 256).

Speaking of PayloadTooLarge, perhaps it'd make sense to replace the Wai's general PayloadTooLarge error with a form-specific construtor in RequestParseException. I'm very strict in handling all errors and right now the Wai Parse module's error cases aren't totally expressible with RequestParseException. PayloadTooLarge also loses information about whether it was a param that was too large or a file. Equally, it'd be nice if the error(s) included the max sizes, too, for better end-user error messages. Right now they contain the actual sizes.

Thanks and cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant