-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Arithmetic Overflow on large HTTP response #13987
Comments
FWIW in this case you'd prob be better off streaming the file instead of loading it all into memory. Something like: File.open "large.file", "w" do |file|
HTTP::Client.get "https://some.url.that.returns.a.large.file/" do |resp|
IO.copy resp.body_io, file
end
end |
That's a good idea, I was trying to avoid that for speed reasons but I might have to just do it and pair it with a ramfs to compensate |
As a workaround without storing to disk, you could also copy the file into a byte buffer as long as you ensure it's big enough. io = IO::Memory.new(Int32::MAX) # or chose smaller, fitting size if you know it in advance
HTTP::Client.get "https://some.url.that.returns.a.large.file/" do |resp|
IO.copy resp.body_io, io
end Maybe you don't need all data in memory though and you can just start consuming it on the go? |
This is a very interesting problem with different layers. I think the generic, dynamically growing byte buffer should clamp to fit the maximum size (i.e. Another issue is specific to the HTTP client: Not sure if it's the case with this particular HTTP resource, but it would be quite likely for the HTTP response to contain a |
This seems to be working for me. Although when using the content length (which I do know in advance) to initialize the |
Not sure what exactly is happing there, but if a |
Apologies if this has already been reported before, I wasn't able to find it.
I was using the following code to download a large file (1.1 GB).
Unfortunately I can't include the real URL because it's not publicly accessible but it's fairly easy to replicate. I got an
Arithmetic Overflow
exception with the following backtrace:Looking through the referenced code it appears the issue is
HTTP::Client
tries to resize the internal buffer it's using to store the response to the next largest power of 2. 1.1 GB is slightly more than 2³⁰ bytes so the next one up is 2³¹ or 2,147,483,648. That's 1 beyond the max of the signed 32 bit integer being used to store the size, resulting in an overflow and crash.Is this intended behavior? Is there any way to switch Crystal to use 64 bit integers for memory/container sizes or any plans to change the default? 2³⁰ bytes isn't that high of a limit for some applications.
This occurred on Crystal 1.10.1.
The text was updated successfully, but these errors were encountered: