Skip to content

Commit 085ee83

Browse files
committed
Prevent data corruption when decoding gzip stream, fixes #284
This fixes an issue where a gzip stream chunked into smaller pieces would result in a buffer overrun when decoding the headers. Previously the position where the headers end in `compressed` was determined by the delta of `@pos` before and after reading the headers. This didn't take into account the fact that `@data` may already contain data, but not enough to have advanced `@pos` on previous iterations.
1 parent 901b546 commit 085ee83

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

lib/em-http/decoders.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ def eof?
127127

128128
def extract_stream(compressed)
129129
@data << compressed
130-
pos = @pos
131130

132131
while !eof? && !finished?
133132
buffer = ""
@@ -208,7 +207,7 @@ def extract_stream(compressed)
208207
end
209208

210209
if finished?
211-
compressed[(@pos - pos)..-1]
210+
compressed[(@pos - (@data.length - compressed.length))..-1]
212211
else
213212
""
214213
end

spec/gzip_spec.rb

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,29 @@
5656
decompressed.size.should eq(32907)
5757
end
5858

59+
it "should not care how many chunks the file is split up into" do
60+
examples = [
61+
["\x1F", "\x8B", "\b", "\x00", "\x00", "\x00", "\x00", "\x00", "\x00", "\x00", "\xF3", "\xCB", "/", "Q", "p\xCB/\xCDK\x01\x00M\x8Ct\xB1\t\x00\x00\x00"],
62+
["\x1F", "\x8B", "\b", "\x00", "\x00", "\x00", "\x00", "\x00\x00\x00\xF3\xCB/Qp\xCB/\xCDK\x01\x00M\x8Ct\xB1\t\x00\x00\x00"]
63+
]
64+
65+
examples.each do |example|
66+
decompressed = ""
67+
68+
gz = EventMachine::HttpDecoders::GZip.new do |data|
69+
decompressed << data
70+
end
71+
72+
example.each do |bytes|
73+
gz << bytes
74+
end
75+
76+
gz.finalize!
77+
78+
decompressed.should eq("Not Found")
79+
end
80+
end
81+
5982
it "should fail with a DecoderError if not a gzip file" do
6083
not_a_gzip = ["1f8c08089668a650000"].pack("H*")
6184
header = EventMachine::HttpDecoders::GZipHeader.new

0 commit comments

Comments
 (0)