diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-28 00:35:09 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-28 00:35:09 +0000 |
commit | 8057dadcea6e36451359362458275b1423ed6f5a (patch) | |
tree | 177d22c69821d23daf2bdcb7b4ff875a817d4098 | |
parent | 1239e944d019142d816dec8b897b53d7462584a5 (diff) | |
download | chromium_src-8057dadcea6e36451359362458275b1423ed6f5a.zip chromium_src-8057dadcea6e36451359362458275b1423ed6f5a.tar.gz chromium_src-8057dadcea6e36451359362458275b1423ed6f5a.tar.bz2 |
Revert 153496 - Merge 151720 - net: workaround compression leaks
(This is a reland of r151502, which was reverted in r151517 because it
broke the Linux Official build.)
This may break the Official build for a brief window while a two-sided
patch lands.
BUG=139744
Review URL: https://chromiumcodereview.appspot.com/10837057
TBR=agl@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10874087
TBR=agl@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10880081
git-svn-id: svn://svn.chromium.org/chrome/branches/1180/src@153595 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/spdy/buffered_spdy_framer.cc | 5 | ||||
-rw-r--r-- | net/spdy/buffered_spdy_framer.h | 1 | ||||
-rw-r--r-- | net/spdy/spdy_framer.cc | 178 | ||||
-rw-r--r-- | net/spdy/spdy_framer.h | 10 | ||||
-rw-r--r-- | net/spdy/spdy_framer_test.cc | 80 | ||||
-rw-r--r-- | third_party/zlib/README.chromium | 3 | ||||
-rw-r--r-- | third_party/zlib/deflate.c | 250 | ||||
-rw-r--r-- | third_party/zlib/deflate.h | 5 | ||||
-rw-r--r-- | third_party/zlib/mixed-source.patch | 491 | ||||
-rw-r--r-- | third_party/zlib/zlib.gyp | 10 | ||||
-rw-r--r-- | third_party/zlib/zlib.h | 12 |
11 files changed, 89 insertions, 956 deletions
diff --git a/net/spdy/buffered_spdy_framer.cc b/net/spdy/buffered_spdy_framer.cc index 91eadbd..b544dcb 100644 --- a/net/spdy/buffered_spdy_framer.cc +++ b/net/spdy/buffered_spdy_framer.cc @@ -252,6 +252,11 @@ bool BufferedSpdyFramer::IsCompressible(const SpdyFrame& frame) const { return spdy_framer_.IsCompressible(frame); } +SpdyControlFrame* BufferedSpdyFramer::CompressControlFrame( + const SpdyControlFrame& frame) { + return spdy_framer_.CompressControlFrame(frame); +} + // static void BufferedSpdyFramer::set_enable_compression_default(bool value) { g_enable_compression_default = value; diff --git a/net/spdy/buffered_spdy_framer.h b/net/spdy/buffered_spdy_framer.h index 0fc6fa7..494238e 100644 --- a/net/spdy/buffered_spdy_framer.h +++ b/net/spdy/buffered_spdy_framer.h @@ -143,6 +143,7 @@ class NET_EXPORT_PRIVATE BufferedSpdyFramer SpdyDataFlags flags); SpdyPriority GetHighestPriority() const; bool IsCompressible(const SpdyFrame& frame) const; + SpdyControlFrame* CompressControlFrame(const SpdyControlFrame& frame); // Specify if newly created SpdySessions should have compression enabled. static void set_enable_compression_default(bool value); diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc index a1fc5eea..3a2ad73 100644 --- a/net/spdy/spdy_framer.cc +++ b/net/spdy/spdy_framer.cc @@ -661,155 +661,6 @@ void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame, } } -// These constants are used by zlib to differentiate between normal data and -// cookie data. Cookie data is handled specially by zlib when compressing. -enum ZDataClass { - // kZStandardData is compressed normally, save that it will never match - // against any other class of data in the window. - kZStandardData = Z_CLASS_STANDARD, - // kZCookieData is compressed in its own Huffman blocks and only matches in - // its entirety and only against other kZCookieData blocks. Any matches must - // be preceeded by a kZStandardData byte, or a semicolon to prevent matching - // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent - // prefix matches. - kZCookieData = Z_CLASS_COOKIE, - // kZHuffmanOnlyData is only Huffman compressed - no matches are performed - // against the window. - kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY, -}; - -// WriteZ writes |data| to the deflate context |out|. WriteZ will flush as -// needed when switching between classes of data. -static void WriteZ(const base::StringPiece& data, - ZDataClass clas, - z_stream* out) { - int rv; - - // If we are switching from standard to non-standard data then we need to end - // the current Huffman context to avoid it leaking between them. - if (out->clas == kZStandardData && - clas != kZStandardData) { - out->avail_in = 0; - rv = deflate(out, Z_PARTIAL_FLUSH); - DCHECK_EQ(Z_OK, rv); - DCHECK_EQ(0u, out->avail_in); - DCHECK_LT(0u, out->avail_out); - } - - out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data())); - out->avail_in = data.size(); - out->clas = clas; - if (clas == kZStandardData) { - rv = deflate(out, Z_NO_FLUSH); - } else { - rv = deflate(out, Z_PARTIAL_FLUSH); - } - DCHECK_EQ(Z_OK, rv); - DCHECK_EQ(0u, out->avail_in); - DCHECK_LT(0u, out->avail_out); -} - -// WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|. -static void WriteLengthZ(size_t n, - unsigned length, - ZDataClass clas, - z_stream* out) { - char buf[4]; - DCHECK_LE(length, sizeof(buf)); - for (unsigned i = 1; i <= length; i++) { - buf[length - i] = n; - n >>= 8; - } - WriteZ(base::StringPiece(buf, length), clas, out); -} - -// WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a -// manner that resists the length of the compressed data from compromising -// cookie data. -void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers, - z_stream* z) const { - unsigned length_length = 4; - if (spdy_version_ < 3) - length_length = 2; - - WriteLengthZ(headers->size(), length_length, kZStandardData, z); - - std::map<std::string, std::string>::const_iterator it; - for (it = headers->begin(); it != headers->end(); ++it) { - WriteLengthZ(it->first.size(), length_length, kZStandardData, z); - WriteZ(it->first, kZStandardData, z); - - if (it->first == "cookie") { - // We require the cookie values to end with a semi-colon and (save for - // the first) to start with one too. The values are already separated by - // semicolons in the header, but there's usually whitespace in there too. - // So we accumulate the values without whitespace in |cookie_values| and - // write them out, along with a final semicolon to terminate the last - // cookie. - - std::string last_cookie; - std::vector<base::StringPiece> cookie_values; - size_t cookie_length = 0; - base::StringPiece cookie_data(it->second); - - for (;;) { - while (!cookie_data.empty() && - (cookie_data[0] == ' ' || cookie_data[0] == '\t')) { - cookie_data.remove_prefix(1); - } - if (cookie_data.empty()) - break; - - size_t i; - for (i = 0; i < cookie_data.size(); i++) { - if (cookie_data[i] == ';') - break; - } - if (i < cookie_data.size()) { - cookie_values.push_back(cookie_data.substr(0, i+1)); - cookie_length += i+1; - cookie_data.remove_prefix(i + 1); - } else { - last_cookie = cookie_data.as_string() + ";"; - cookie_values.push_back(last_cookie); - cookie_length += last_cookie.size(); - cookie_data.remove_prefix(i); - } - } - - WriteLengthZ(cookie_length, length_length, kZStandardData, z); - for (std::vector<base::StringPiece>::const_iterator - i = cookie_values.begin(); i != cookie_values.end(); i++) { - WriteZ(*i, kZCookieData, z); - } - } else if (it->first == "accept" || - it->first == "accept-charset" || - it->first == "accept-encoding" || - it->first == "accept-language" || - it->first == "host" || - it->first == "version" || - it->first == "method" || - it->first == "scheme" || - it->first == ":host" || - it->first == ":version" || - it->first == ":method" || - it->first == ":scheme" || - it->first == "user-agent") { - WriteLengthZ(it->second.size(), length_length, kZStandardData, z); - WriteZ(it->second, kZStandardData, z); - } else { - // Non-whitelisted headers are Huffman compressed in their own block, but - // don't match against the window. - WriteLengthZ(it->second.size(), length_length, kZStandardData, z); - WriteZ(it->second, kZHuffmanOnlyData, z); - } - } - - z->avail_in = 0; - int rv = deflate(z, Z_SYNC_FLUSH); - DCHECK_EQ(Z_OK, rv); - z->clas = kZStandardData; -} size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, size_t len) { @@ -1202,7 +1053,7 @@ SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( reinterpret_cast<SpdySynStreamControlFrame*>(frame.take())); if (compressed) { return reinterpret_cast<SpdySynStreamControlFrame*>( - CompressControlFrame(*syn_frame.get(), headers)); + CompressControlFrame(*syn_frame.get())); } return syn_frame.release(); } @@ -1235,7 +1086,7 @@ SpdySynReplyControlFrame* SpdyFramer::CreateSynReply( reinterpret_cast<SpdySynReplyControlFrame*>(frame.take())); if (compressed) { return reinterpret_cast<SpdySynReplyControlFrame*>( - CompressControlFrame(*reply_frame.get(), headers)); + CompressControlFrame(*reply_frame.get())); } return reply_frame.release(); } @@ -1331,7 +1182,7 @@ SpdyHeadersControlFrame* SpdyFramer::CreateHeaders( reinterpret_cast<SpdyHeadersControlFrame*>(frame.take())); if (compressed) { return reinterpret_cast<SpdyHeadersControlFrame*>( - CompressControlFrame(*headers_frame.get(), headers)); + CompressControlFrame(*headers_frame.get())); } return headers_frame.release(); } @@ -1511,8 +1362,7 @@ bool SpdyFramer::GetFrameBoundaries(const SpdyFrame& frame, } SpdyControlFrame* SpdyFramer::CompressControlFrame( - const SpdyControlFrame& frame, - const SpdyHeaderBlock* headers) { + const SpdyControlFrame& frame) { z_stream* compressor = GetHeaderCompressor(); if (!compressor) return NULL; @@ -1533,10 +1383,6 @@ SpdyControlFrame* SpdyFramer::CompressControlFrame( // Create an output frame. int compressed_max_size = deflateBound(compressor, payload_length); - // Since we'll be performing lots of flushes when compressing the data, - // zlib's lower bounds may be insufficient. - compressed_max_size *= 2; - size_t new_frame_size = header_length + compressed_max_size; if ((frame.type() == SYN_REPLY || frame.type() == HEADERS) && spdy_version_ < 3) { @@ -1547,10 +1393,24 @@ SpdyControlFrame* SpdyFramer::CompressControlFrame( memcpy(new_frame->data(), frame.data(), frame.length() + SpdyFrame::kHeaderSize); + compressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); + compressor->avail_in = payload_length; compressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) + header_length; compressor->avail_out = compressed_max_size; - WriteHeaderBlockToZ(headers, compressor); + + // Make sure that all the data we pass to zlib is defined. + // This way, all Valgrind reports on the compressed data are zlib's fault. + (void)VALGRIND_CHECK_MEM_IS_DEFINED(compressor->next_in, + compressor->avail_in); + + int rv = deflate(compressor, Z_SYNC_FLUSH); + if (rv != Z_OK) { // How can we know that it compressed everything? + // This shouldn't happen, right? + LOG(WARNING) << "deflate failure: " << rv; + return NULL; + } + int compressed_size = compressed_max_size - compressor->avail_out; // We trust zlib. Also, we can't do anything about it. diff --git a/net/spdy/spdy_framer.h b/net/spdy/spdy_framer.h index 1970838..63570a6 100644 --- a/net/spdy/spdy_framer.h +++ b/net/spdy/spdy_framer.h @@ -386,6 +386,9 @@ class NET_EXPORT_PRIVATE SpdyFramer { // Returns true if a frame could be compressed. bool IsCompressible(const SpdyFrame& frame) const; + // Returns a new SpdyControlFrame with the compressed payload of |frame|. + SpdyControlFrame* CompressControlFrame(const SpdyControlFrame& frame); + // Get the minimum size of the control frame for the given control frame // type. This is useful for validating frame blocks. static size_t GetMinimumControlFrameSize(int version, SpdyControlType type); @@ -494,9 +497,6 @@ class NET_EXPORT_PRIVATE SpdyFramer { void WriteHeaderBlock(SpdyFrameBuilder* frame, const SpdyHeaderBlock* headers) const; - void WriteHeaderBlockToZ(const SpdyHeaderBlock* headers, - z_stream* out) const; - // Set the error code and moves the framer into the error state. void set_error(SpdyError error); @@ -505,10 +505,6 @@ class NET_EXPORT_PRIVATE SpdyFramer { bool GetFrameBoundaries(const SpdyFrame& frame, int* payload_length, int* header_length, const char** payload) const; - // Returns a new SpdyControlFrame with the compressed payload of |frame|. - SpdyControlFrame* CompressControlFrame(const SpdyControlFrame& frame, - const SpdyHeaderBlock* headers); - // The size of the control frame buffer. // Since this is only used for control frame headers, the maximum control // frame header size (SYN_STREAM) is sufficient; all remaining control diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc index ab021a9..fd80da4 100644 --- a/net/spdy/spdy_framer_test.cc +++ b/net/spdy/spdy_framer_test.cc @@ -1586,39 +1586,31 @@ TEST_P(SpdyFramerTest, CreateSynStreamCompressed) { const SpdyPriority priority = IsSpdy2() ? 2 : 4; const unsigned char kV2FrameData[] = { 0x80, spdy_version_, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x36, + 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x38, 0xea, 0xdf, 0xa2, 0x51, 0xb2, 0x62, 0x60, 0x62, 0x60, 0x4e, 0x4a, 0x2c, 0x62, - 0x60, 0x06, 0x08, 0xa0, - 0xb4, 0xfc, 0x7c, 0x80, - 0x00, 0x62, 0x60, 0x4e, - 0xcb, 0xcf, 0x67, 0x60, - 0x06, 0x08, 0xa0, 0xa4, - 0xc4, 0x22, 0x80, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0xff, 0xff, + 0x60, 0x4e, 0xcb, 0xcf, + 0x87, 0x12, 0x40, 0x2e, + 0x00, 0x00, 0x00, 0xff, + 0xff }; const unsigned char kV3FrameData[] = { 0x80, spdy_version_, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x37, + 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x38, 0xEA, 0xE3, 0xC6, 0xA7, 0xC2, 0x02, 0xE5, 0x0E, 0x50, 0xC2, 0x4B, 0x4A, 0x04, - 0xE5, 0x0B, 0x66, 0x80, - 0x00, 0x4A, 0xCB, 0xCF, - 0x07, 0x08, 0x20, 0x10, - 0x95, 0x96, 0x9F, 0x0F, - 0xA2, 0x00, 0x02, 0x28, - 0x29, 0xB1, 0x08, 0x20, - 0x80, 0x00, 0x00, 0x00, - 0x00, 0xFF, 0xFF, + 0xE5, 0x0B, 0xE6, 0xB4, + 0xFC, 0x7C, 0x24, 0x0A, + 0x28, 0x08, 0x00, 0x00, + 0x00, 0xFF, 0xFF }; scoped_ptr<SpdyFrame> frame( framer.CreateSynStream(1, // stream id @@ -1772,37 +1764,29 @@ TEST_P(SpdyFramerTest, CreateSynReplyCompressed) { const unsigned char kV2FrameData[] = { 0x80, spdy_version_, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x38, 0xea, 0xdf, 0xa2, 0x51, 0xb2, 0x62, 0x60, 0x62, 0x60, 0x4e, 0x4a, 0x2c, 0x62, - 0x60, 0x06, 0x08, 0xa0, - 0xb4, 0xfc, 0x7c, 0x80, - 0x00, 0x62, 0x60, 0x4e, - 0xcb, 0xcf, 0x67, 0x60, - 0x06, 0x08, 0xa0, 0xa4, - 0xc4, 0x22, 0x80, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0xff, 0xff, + 0x60, 0x4e, 0xcb, 0xcf, + 0x87, 0x12, 0x40, 0x2e, + 0x00, 0x00, 0x00, 0xff, + 0xff }; const unsigned char kV3FrameData[] = { 0x80, spdy_version_, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x38, 0xea, 0xe3, 0xc6, 0xa7, 0xc2, 0x02, 0xe5, 0x0e, 0x50, 0xc2, 0x4b, 0x4a, 0x04, 0xe5, 0x0b, - 0x66, 0x80, 0x00, 0x4a, - 0xcb, 0xcf, 0x07, 0x08, - 0x20, 0x10, 0x95, 0x96, - 0x9f, 0x0f, 0xa2, 0x00, - 0x02, 0x28, 0x29, 0xb1, - 0x08, 0x20, 0x80, 0x00, + 0xe6, 0xb4, 0xfc, 0x7c, + 0x24, 0x0a, 0x28, 0x08, 0x00, 0x00, 0x00, 0xff, - 0xff, + 0xff }; scoped_ptr<SpdyFrame> frame(framer.CreateSynReply( 1, CONTROL_FLAG_NONE, true, &headers)); @@ -2164,37 +2148,29 @@ TEST_P(SpdyFramerTest, CreateHeadersCompressed) { const unsigned char kV2FrameData[] = { 0x80, spdy_version_, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x38, 0xea, 0xdf, 0xa2, 0x51, 0xb2, 0x62, 0x60, 0x62, 0x60, 0x4e, 0x4a, 0x2c, 0x62, - 0x60, 0x06, 0x08, 0xa0, - 0xb4, 0xfc, 0x7c, 0x80, - 0x00, 0x62, 0x60, 0x4e, - 0xcb, 0xcf, 0x67, 0x60, - 0x06, 0x08, 0xa0, 0xa4, - 0xc4, 0x22, 0x80, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0xff, 0xff, + 0x60, 0x4e, 0xcb, 0xcf, + 0x87, 0x12, 0x40, 0x2e, + 0x00, 0x00, 0x00, 0xff, + 0xff }; const unsigned char kV3FrameData[] = { 0x80, spdy_version_, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x31, + 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0x38, 0xea, 0xe3, 0xc6, 0xa7, 0xc2, 0x02, 0xe5, 0x0e, 0x50, 0xc2, 0x4b, 0x4a, 0x04, 0xe5, 0x0b, - 0x66, 0x80, 0x00, 0x4a, - 0xcb, 0xcf, 0x07, 0x08, - 0x20, 0x10, 0x95, 0x96, - 0x9f, 0x0f, 0xa2, 0x00, - 0x02, 0x28, 0x29, 0xb1, - 0x08, 0x20, 0x80, 0x00, + 0xe6, 0xb4, 0xfc, 0x7c, + 0x24, 0x0a, 0x28, 0x08, 0x00, 0x00, 0x00, 0xff, - 0xff, + 0xff }; scoped_ptr<SpdyFrame> frame(framer.CreateHeaders( 1, CONTROL_FLAG_NONE, true, &headers)); diff --git a/third_party/zlib/README.chromium b/third_party/zlib/README.chromium index 05016f1..9fc04d1 100644 --- a/third_party/zlib/README.chromium +++ b/third_party/zlib/README.chromium @@ -14,6 +14,3 @@ A few minor changes, all marked with "Google": - Added 'mozzconf.h' to mangle the function names. - Added an #ifdef to prevent zlib.h from mangling its functions. The 'google.patch' file represents our changes from the original zlib-1.2.5. - -A more significant change to support mixed-source data compression. See -crbug.com/139744 and mixed-source.patch. diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c index 02d1516..5c4022f 100644 --- a/third_party/zlib/deflate.c +++ b/third_party/zlib/deflate.c @@ -70,15 +70,14 @@ typedef enum { finish_done /* finish done, accept no more input or output */ } block_state; -typedef block_state (*compress_func) OF((deflate_state *s, int flush, - int clas)); +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); /* Compression function. Returns the block state after the call. */ local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush, int clas)); -local block_state deflate_fast OF((deflate_state *s, int flush, int clas)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); #ifndef FASTEST -local block_state deflate_slow OF((deflate_state *s, int flush, int clas)); +local block_state deflate_slow OF((deflate_state *s, int flush)); #endif local block_state deflate_rle OF((deflate_state *s, int flush)); local block_state deflate_huff OF((deflate_state *s, int flush)); @@ -88,9 +87,9 @@ local void flush_pending OF((z_streamp strm)); local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); #ifdef ASMV void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match, int clas)); + uInt longest_match OF((deflate_state *s, IPos cur_match)); #else -local uInt longest_match OF((deflate_state *s, IPos cur_match, int clas)); +local uInt longest_match OF((deflate_state *s, IPos cur_match)); #endif #ifdef DEBUG @@ -282,9 +281,6 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); - s->class_bitmap = NULL; - zmemzero(&s->cookie_locations, sizeof(s->cookie_locations)); - strm->clas = 0; s->high_water = 0; /* nothing written to s->window yet */ @@ -371,8 +367,6 @@ int ZEXPORT deflateReset (strm) s = (deflate_state *)strm->state; s->pending = 0; s->pending_out = s->pending_buf; - TRY_FREE(strm, s->class_bitmap); - s->class_bitmap = NULL; if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ @@ -823,26 +817,9 @@ int ZEXPORT deflate (strm, flush) (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; - if (strm->clas && s->class_bitmap == NULL) { - /* This is the first time that we have seen alternative class - * data. All data up till this point has been standard class. */ - s->class_bitmap = (Bytef*) ZALLOC(strm, s->w_size/4, sizeof(Byte)); - zmemzero(s->class_bitmap, s->w_size/4); - } - - if (strm->clas && s->strategy == Z_RLE) { - /* We haven't patched deflate_rle. */ - ERR_RETURN(strm, Z_BUF_ERROR); - } - - if (s->strategy == Z_HUFFMAN_ONLY) { - bstate = deflate_huff(s, flush); - } else if (s->strategy == Z_RLE) { - bstate = deflate_rle(s, flush); - } else { - bstate = (*(configuration_table[s->level].func)) - (s, flush, strm->clas); - } + bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + (s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush)); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; @@ -938,7 +915,6 @@ int ZEXPORT deflateEnd (strm) TRY_FREE(strm, strm->state->head); TRY_FREE(strm, strm->state->prev); TRY_FREE(strm, strm->state->window); - TRY_FREE(strm, strm->state->class_bitmap); ZFREE(strm, strm->state); strm->state = Z_NULL; @@ -1070,57 +1046,6 @@ local void lm_init (s) #endif } -/* class_set sets bits [offset,offset+len) in s->class_bitmap to either 1 (if - * class != 0) or 0 (otherwise). */ -local void class_set(s, offset, len, clas) - deflate_state *s; - IPos offset; - uInt len; - int clas; -{ - IPos byte = offset >> 3; - IPos bit = offset & 7; - Bytef class_byte_value = clas ? 0xff : 0x00; - Bytef class_bit_value = clas ? 1 : 0; - static const Bytef mask[8] = {0xfe, 0xfd, 0xfb, 0xf7, - 0xef, 0xdf, 0xbf, 0x7f}; - - if (bit) { - while (len) { - s->class_bitmap[byte] &= mask[bit]; - s->class_bitmap[byte] |= class_bit_value << bit; - bit++; - len--; - if (bit == 8) { - bit = 0; - byte++; - break; - } - } - } - - while (len >= 8) { - s->class_bitmap[byte++] = class_byte_value; - len -= 8; - } - - while (len) { - s->class_bitmap[byte] &= mask[bit]; - s->class_bitmap[byte] |= class_bit_value << bit; - bit++; - len--; - } -} - -local int class_at(s, window_offset) - deflate_state *s; - IPos window_offset; -{ - IPos byte = window_offset >> 3; - IPos bit = window_offset & 7; - return (s->class_bitmap[byte] >> bit) & 1; -} - #ifndef FASTEST /* =========================================================================== * Set match_start to the longest match starting at the given string and @@ -1135,10 +1060,9 @@ local int class_at(s, window_offset) /* For 80x86 and 680x0, an optimized version will be provided in match.asm or * match.S. The code will be functionally equivalent. */ -local uInt longest_match(s, cur_match, clas) +local uInt longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ - int clas; { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ @@ -1186,9 +1110,6 @@ local uInt longest_match(s, cur_match, clas) do { Assert(cur_match < s->strstart, "no future"); match = s->window + cur_match; - /* If the matched data is in the wrong class, skip it. */ - if (s->class_bitmap && class_at(s, cur_match) != clas) - continue; /* Skip to next match if the match length cannot increase * or if the match length is less than 2. Note that the checks below @@ -1231,8 +1152,6 @@ local uInt longest_match(s, cur_match, clas) len = (MAX_MATCH - 1) - (int)(strend-scan); scan = strend - (MAX_MATCH-1); -#error "UNALIGNED_OK hasn't been patched." - #else /* UNALIGNED_OK */ if (match[best_len] != scan_end || @@ -1249,23 +1168,15 @@ local uInt longest_match(s, cur_match, clas) scan += 2, match++; Assert(*scan == *match, "match[2]?"); - if (!s->class_bitmap) { - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - } else { - /* We have to be mindful of the class of the data and not stray. */ - do { - } while (*++scan == *++match && - class_at(s, match - s->window) == clas && - scan < strend); - } + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); @@ -1293,67 +1204,20 @@ local uInt longest_match(s, cur_match, clas) } #endif /* ASMV */ -/* cookie_match is a replacement for longest_match in the case of cookie data. - * Here we only wish to match the entire value so trying the partial matches in - * longest_match is both wasteful and often fails to find the correct match. - * - * So we take the djb2 hash of the cookie and look up the last position for a - * match in a special hash table. */ -local uInt cookie_match(s, start, len) - deflate_state *s; - IPos start; - unsigned len; -{ - unsigned hash = 5381; - Bytef *str = s->window + start; - unsigned i; - IPos cookie_location; - - if (len >= MAX_MATCH) - return 0; - - for (i = 0; i < len; i++) - hash = ((hash << 5) + hash) + str[i]; - - hash &= Z_COOKIE_HASH_MASK; - cookie_location = s->cookie_locations[hash]; - s->cookie_locations[hash] = start; - s->match_start = 0; - if (cookie_location && - (start - cookie_location) > len && - (start - cookie_location) < MAX_DIST(s) && - len <= s->lookahead) { - for (i = 0; i < len; i++) { - if (s->window[start+i] != s->window[cookie_location+i] || - class_at(s, cookie_location+i) != 1) { - return 0; - } - } - s->match_start = cookie_location; - return len; - } - - return 0; -} - - #else /* FASTEST */ /* --------------------------------------------------------------------------- * Optimized version for FASTEST only */ -local uInt longest_match(s, cur_match, clas) +local uInt longest_match(s, cur_match) deflate_state *s; IPos cur_match; /* current match */ - int clas; { register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *match; /* matched string */ register int len; /* length of current match */ register Bytef *strend = s->window + s->strstart + MAX_MATCH; -#error "This code not patched" - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ @@ -1496,21 +1360,6 @@ local void fill_window(s) */ } while (--n); #endif - - for (n = 0; n < Z_COOKIE_HASH_SIZE; n++) { - if (s->cookie_locations[n] > wsize) { - s->cookie_locations[n] -= wsize; - } else { - s->cookie_locations[n] = 0; - } - } - - if (s->class_bitmap) { - zmemcpy(s->class_bitmap, s->class_bitmap + s->w_size/8, - s->w_size/8); - zmemzero(s->class_bitmap + s->w_size/8, s->w_size/8); - } - more += wsize; } if (s->strm->avail_in == 0) return; @@ -1529,9 +1378,6 @@ local void fill_window(s) Assert(more >= 2, "more < 2"); n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - if (s->class_bitmap != NULL) { - class_set(s, s->strstart + s->lookahead, n, s->strm->clas); - } s->lookahead += n; /* Initialize the hash value now that we have some input: */ @@ -1613,10 +1459,9 @@ local void fill_window(s) * NOTE: this function should be optimized to avoid extra copying from * window to pending_buf. */ -local block_state deflate_stored(s, flush, clas) +local block_state deflate_stored(s, flush) deflate_state *s; int flush; - int clas; { /* Stored blocks are limited to 0xffff bytes, pending_buf is limited * to pending_buf_size, and each stored block has a 5 byte header: @@ -1672,19 +1517,13 @@ local block_state deflate_stored(s, flush, clas) * new strings in the dictionary only for unmatched strings or for short * matches. It is used only for the fast compression options. */ -local block_state deflate_fast(s, flush, clas) +local block_state deflate_fast(s, flush) deflate_state *s; int flush; - int clas; { IPos hash_head; /* head of the hash chain */ int bflush; /* set if current block must be flushed */ - if (clas != 0) { - /* We haven't patched this code for alternative class data. */ - return Z_BUF_ERROR; - } - for (;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need MAX_MATCH bytes @@ -1715,7 +1554,7 @@ local block_state deflate_fast(s, flush, clas) * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ - s->match_length = longest_match (s, hash_head, clas); + s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ } if (s->match_length >= MIN_MATCH) { @@ -1774,25 +1613,12 @@ local block_state deflate_fast(s, flush, clas) * evaluation for matches: a match is finally adopted only if there is * no better match at the next window position. */ -local block_state deflate_slow(s, flush, clas) +local block_state deflate_slow(s, flush) deflate_state *s; int flush; - int clas; { IPos hash_head; /* head of hash chain */ int bflush; /* set if current block must be flushed */ - uInt input_length ; - int first = 1; /* first says whether this is the first iteration - of the loop, below. */ - - if (clas == Z_CLASS_COOKIE) { - if (s->lookahead) { - /* Alternative class data must always be presented at the beginning - * of a block. */ - return Z_BUF_ERROR; - } - input_length = s->strm->avail_in; - } /* Process the input block. */ for (;;) { @@ -1822,18 +1648,13 @@ local block_state deflate_slow(s, flush, clas) s->prev_length = s->match_length, s->prev_match = s->match_start; s->match_length = MIN_MATCH-1; - if (clas == Z_CLASS_COOKIE && first) { - s->match_length = cookie_match(s, s->strstart, input_length); - } else if (clas == Z_CLASS_STANDARD && - hash_head != NIL && - s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ - s->match_length = longest_match (s, hash_head, clas); - + s->match_length = longest_match (s, hash_head); /* longest_match() sets match_start */ if (s->match_length <= 5 && (s->strategy == Z_FILTERED @@ -1852,22 +1673,7 @@ local block_state deflate_slow(s, flush, clas) /* If there was a match at the previous step and the current * match is not better, output the previous match: */ - first = 0; - if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length && - /* We will only accept an exact match for Z_CLASS_COOKIE data and - * we won't match Z_CLASS_HUFFMAN_ONLY data at all. */ - (clas == Z_CLASS_STANDARD || (clas == Z_CLASS_COOKIE && - s->prev_length == input_length && - s->prev_match > 0 && - /* We require that a Z_CLASS_COOKIE match be - * preceded by either a semicolon (which cannot be - * part of a cookie), or non-cookie data. This is - * to prevent - * a cookie from being a prefix of another. - * spdy_framer.cc ensures that cookies are always - * terminated by a semicolon. */ - (class_at(s, s->prev_match-1) == Z_CLASS_STANDARD || - *(s->window + s->prev_match-1) == ';')))) { + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; /* Do not insert strings in hash table beyond this. */ diff --git a/third_party/zlib/deflate.h b/third_party/zlib/deflate.h index 83b4602..cbf0d1e 100644 --- a/third_party/zlib/deflate.h +++ b/third_party/zlib/deflate.h @@ -91,9 +91,6 @@ typedef unsigned IPos; * save space in the various tables. IPos is used only for parameter passing. */ -#define Z_COOKIE_HASH_SIZE 64 -#define Z_COOKIE_HASH_MASK (Z_COOKIE_HASH_SIZE-1) - typedef struct internal_state { z_streamp strm; /* pointer back to this zlib stream */ int status; /* as the name implies */ @@ -142,8 +139,6 @@ typedef struct internal_state { uInt hash_mask; /* hash_size-1 */ uInt hash_shift; - Bytef *class_bitmap; /* bitmap of class for each byte in window */ - IPos cookie_locations[Z_COOKIE_HASH_SIZE]; /* Number of bits by which ins_h must be shifted at each input * step. It must be such that after MIN_MATCH steps, the oldest * byte no longer takes part in the hash key, that is: diff --git a/third_party/zlib/mixed-source.patch b/third_party/zlib/mixed-source.patch deleted file mode 100644 index bd55ef4..0000000 --- a/third_party/zlib/mixed-source.patch +++ /dev/null @@ -1,491 +0,0 @@ -diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c -index 5c4022f..02d1516 100644 ---- a/third_party/zlib/deflate.c -+++ b/third_party/zlib/deflate.c -@@ -70,14 +70,15 @@ typedef enum { - finish_done /* finish done, accept no more input or output */ - } block_state; - --typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -+typedef block_state (*compress_func) OF((deflate_state *s, int flush, -+ int clas)); - /* Compression function. Returns the block state after the call. */ - - local void fill_window OF((deflate_state *s)); --local block_state deflate_stored OF((deflate_state *s, int flush)); --local block_state deflate_fast OF((deflate_state *s, int flush)); -+local block_state deflate_stored OF((deflate_state *s, int flush, int clas)); -+local block_state deflate_fast OF((deflate_state *s, int flush, int clas)); - #ifndef FASTEST --local block_state deflate_slow OF((deflate_state *s, int flush)); -+local block_state deflate_slow OF((deflate_state *s, int flush, int clas)); - #endif - local block_state deflate_rle OF((deflate_state *s, int flush)); - local block_state deflate_huff OF((deflate_state *s, int flush)); -@@ -87,9 +88,9 @@ local void flush_pending OF((z_streamp strm)); - local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); - #ifdef ASMV - void match_init OF((void)); /* asm code initialization */ -- uInt longest_match OF((deflate_state *s, IPos cur_match)); -+ uInt longest_match OF((deflate_state *s, IPos cur_match, int clas)); - #else --local uInt longest_match OF((deflate_state *s, IPos cur_match)); -+local uInt longest_match OF((deflate_state *s, IPos cur_match, int clas)); - #endif - - #ifdef DEBUG -@@ -281,6 +282,9 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); - s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); -+ s->class_bitmap = NULL; -+ zmemzero(&s->cookie_locations, sizeof(s->cookie_locations)); -+ strm->clas = 0; - - s->high_water = 0; /* nothing written to s->window yet */ - -@@ -367,6 +371,8 @@ int ZEXPORT deflateReset (strm) - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; -+ TRY_FREE(strm, s->class_bitmap); -+ s->class_bitmap = NULL; - - if (s->wrap < 0) { - s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ -@@ -817,9 +823,26 @@ int ZEXPORT deflate (strm, flush) - (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; - -- bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : -- (s->strategy == Z_RLE ? deflate_rle(s, flush) : -- (*(configuration_table[s->level].func))(s, flush)); -+ if (strm->clas && s->class_bitmap == NULL) { -+ /* This is the first time that we have seen alternative class -+ * data. All data up till this point has been standard class. */ -+ s->class_bitmap = (Bytef*) ZALLOC(strm, s->w_size/4, sizeof(Byte)); -+ zmemzero(s->class_bitmap, s->w_size/4); -+ } -+ -+ if (strm->clas && s->strategy == Z_RLE) { -+ /* We haven't patched deflate_rle. */ -+ ERR_RETURN(strm, Z_BUF_ERROR); -+ } -+ -+ if (s->strategy == Z_HUFFMAN_ONLY) { -+ bstate = deflate_huff(s, flush); -+ } else if (s->strategy == Z_RLE) { -+ bstate = deflate_rle(s, flush); -+ } else { -+ bstate = (*(configuration_table[s->level].func)) -+ (s, flush, strm->clas); -+ } - - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; -@@ -915,6 +938,7 @@ int ZEXPORT deflateEnd (strm) - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->prev); - TRY_FREE(strm, strm->state->window); -+ TRY_FREE(strm, strm->state->class_bitmap); - - ZFREE(strm, strm->state); - strm->state = Z_NULL; -@@ -1046,6 +1070,57 @@ local void lm_init (s) - #endif - } - -+/* class_set sets bits [offset,offset+len) in s->class_bitmap to either 1 (if -+ * class != 0) or 0 (otherwise). */ -+local void class_set(s, offset, len, clas) -+ deflate_state *s; -+ IPos offset; -+ uInt len; -+ int clas; -+{ -+ IPos byte = offset >> 3; -+ IPos bit = offset & 7; -+ Bytef class_byte_value = clas ? 0xff : 0x00; -+ Bytef class_bit_value = clas ? 1 : 0; -+ static const Bytef mask[8] = {0xfe, 0xfd, 0xfb, 0xf7, -+ 0xef, 0xdf, 0xbf, 0x7f}; -+ -+ if (bit) { -+ while (len) { -+ s->class_bitmap[byte] &= mask[bit]; -+ s->class_bitmap[byte] |= class_bit_value << bit; -+ bit++; -+ len--; -+ if (bit == 8) { -+ bit = 0; -+ byte++; -+ break; -+ } -+ } -+ } -+ -+ while (len >= 8) { -+ s->class_bitmap[byte++] = class_byte_value; -+ len -= 8; -+ } -+ -+ while (len) { -+ s->class_bitmap[byte] &= mask[bit]; -+ s->class_bitmap[byte] |= class_bit_value << bit; -+ bit++; -+ len--; -+ } -+} -+ -+local int class_at(s, window_offset) -+ deflate_state *s; -+ IPos window_offset; -+{ -+ IPos byte = window_offset >> 3; -+ IPos bit = window_offset & 7; -+ return (s->class_bitmap[byte] >> bit) & 1; -+} -+ - #ifndef FASTEST - /* =========================================================================== - * Set match_start to the longest match starting at the given string and -@@ -1060,9 +1135,10 @@ local void lm_init (s) - /* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ --local uInt longest_match(s, cur_match) -+local uInt longest_match(s, cur_match, clas) - deflate_state *s; - IPos cur_match; /* current match */ -+ int clas; - { - unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register Bytef *scan = s->window + s->strstart; /* current string */ -@@ -1110,6 +1186,9 @@ local uInt longest_match(s, cur_match) - do { - Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; -+ /* If the matched data is in the wrong class, skip it. */ -+ if (s->class_bitmap && class_at(s, cur_match) != clas) -+ continue; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below -@@ -1152,6 +1231,8 @@ local uInt longest_match(s, cur_match) - len = (MAX_MATCH - 1) - (int)(strend-scan); - scan = strend - (MAX_MATCH-1); - -+#error "UNALIGNED_OK hasn't been patched." -+ - #else /* UNALIGNED_OK */ - - if (match[best_len] != scan_end || -@@ -1168,15 +1249,23 @@ local uInt longest_match(s, cur_match) - scan += 2, match++; - Assert(*scan == *match, "match[2]?"); - -- /* We check for insufficient lookahead only every 8th comparison; -- * the 256th check will be made at strstart+258. -- */ -- do { -- } while (*++scan == *++match && *++scan == *++match && -- *++scan == *++match && *++scan == *++match && -- *++scan == *++match && *++scan == *++match && -- *++scan == *++match && *++scan == *++match && -- scan < strend); -+ if (!s->class_bitmap) { -+ /* We check for insufficient lookahead only every 8th comparison; -+ * the 256th check will be made at strstart+258. -+ */ -+ do { -+ } while (*++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ *++scan == *++match && *++scan == *++match && -+ scan < strend); -+ } else { -+ /* We have to be mindful of the class of the data and not stray. */ -+ do { -+ } while (*++scan == *++match && -+ class_at(s, match - s->window) == clas && -+ scan < strend); -+ } - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - -@@ -1204,20 +1293,67 @@ local uInt longest_match(s, cur_match) - } - #endif /* ASMV */ - -+/* cookie_match is a replacement for longest_match in the case of cookie data. -+ * Here we only wish to match the entire value so trying the partial matches in -+ * longest_match is both wasteful and often fails to find the correct match. -+ * -+ * So we take the djb2 hash of the cookie and look up the last position for a -+ * match in a special hash table. */ -+local uInt cookie_match(s, start, len) -+ deflate_state *s; -+ IPos start; -+ unsigned len; -+{ -+ unsigned hash = 5381; -+ Bytef *str = s->window + start; -+ unsigned i; -+ IPos cookie_location; -+ -+ if (len >= MAX_MATCH) -+ return 0; -+ -+ for (i = 0; i < len; i++) -+ hash = ((hash << 5) + hash) + str[i]; -+ -+ hash &= Z_COOKIE_HASH_MASK; -+ cookie_location = s->cookie_locations[hash]; -+ s->cookie_locations[hash] = start; -+ s->match_start = 0; -+ if (cookie_location && -+ (start - cookie_location) > len && -+ (start - cookie_location) < MAX_DIST(s) && -+ len <= s->lookahead) { -+ for (i = 0; i < len; i++) { -+ if (s->window[start+i] != s->window[cookie_location+i] || -+ class_at(s, cookie_location+i) != 1) { -+ return 0; -+ } -+ } -+ s->match_start = cookie_location; -+ return len; -+ } -+ -+ return 0; -+} -+ -+ - #else /* FASTEST */ - - /* --------------------------------------------------------------------------- - * Optimized version for FASTEST only - */ --local uInt longest_match(s, cur_match) -+local uInt longest_match(s, cur_match, clas) - deflate_state *s; - IPos cur_match; /* current match */ -+ int clas; - { - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - -+#error "This code not patched" -+ - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ -@@ -1360,6 +1496,21 @@ local void fill_window(s) - */ - } while (--n); - #endif -+ -+ for (n = 0; n < Z_COOKIE_HASH_SIZE; n++) { -+ if (s->cookie_locations[n] > wsize) { -+ s->cookie_locations[n] -= wsize; -+ } else { -+ s->cookie_locations[n] = 0; -+ } -+ } -+ -+ if (s->class_bitmap) { -+ zmemcpy(s->class_bitmap, s->class_bitmap + s->w_size/8, -+ s->w_size/8); -+ zmemzero(s->class_bitmap + s->w_size/8, s->w_size/8); -+ } -+ - more += wsize; - } - if (s->strm->avail_in == 0) return; -@@ -1378,6 +1529,9 @@ local void fill_window(s) - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); -+ if (s->class_bitmap != NULL) { -+ class_set(s, s->strstart + s->lookahead, n, s->strm->clas); -+ } - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ -@@ -1459,9 +1613,10 @@ local void fill_window(s) - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ --local block_state deflate_stored(s, flush) -+local block_state deflate_stored(s, flush, clas) - deflate_state *s; - int flush; -+ int clas; - { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: -@@ -1517,13 +1672,19 @@ local block_state deflate_stored(s, flush) - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ --local block_state deflate_fast(s, flush) -+local block_state deflate_fast(s, flush, clas) - deflate_state *s; - int flush; -+ int clas; - { - IPos hash_head; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ - -+ if (clas != 0) { -+ /* We haven't patched this code for alternative class data. */ -+ return Z_BUF_ERROR; -+ } -+ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes -@@ -1554,7 +1715,7 @@ local block_state deflate_fast(s, flush) - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ -- s->match_length = longest_match (s, hash_head); -+ s->match_length = longest_match (s, hash_head, clas); - /* longest_match() sets match_start */ - } - if (s->match_length >= MIN_MATCH) { -@@ -1613,12 +1774,25 @@ local block_state deflate_fast(s, flush) - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ --local block_state deflate_slow(s, flush) -+local block_state deflate_slow(s, flush, clas) - deflate_state *s; - int flush; -+ int clas; - { - IPos hash_head; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ -+ uInt input_length ; -+ int first = 1; /* first says whether this is the first iteration -+ of the loop, below. */ -+ -+ if (clas == Z_CLASS_COOKIE) { -+ if (s->lookahead) { -+ /* Alternative class data must always be presented at the beginning -+ * of a block. */ -+ return Z_BUF_ERROR; -+ } -+ input_length = s->strm->avail_in; -+ } - - /* Process the input block. */ - for (;;) { -@@ -1648,13 +1822,18 @@ local block_state deflate_slow(s, flush) - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = MIN_MATCH-1; - -- if (hash_head != NIL && s->prev_length < s->max_lazy_match && -- s->strstart - hash_head <= MAX_DIST(s)) { -+ if (clas == Z_CLASS_COOKIE && first) { -+ s->match_length = cookie_match(s, s->strstart, input_length); -+ } else if (clas == Z_CLASS_STANDARD && -+ hash_head != NIL && -+ s->prev_length < s->max_lazy_match && -+ s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ -- s->match_length = longest_match (s, hash_head); -+ s->match_length = longest_match (s, hash_head, clas); -+ - /* longest_match() sets match_start */ - - if (s->match_length <= 5 && (s->strategy == Z_FILTERED -@@ -1673,7 +1852,22 @@ local block_state deflate_slow(s, flush) - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ -- if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { -+ first = 0; -+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length && -+ /* We will only accept an exact match for Z_CLASS_COOKIE data and -+ * we won't match Z_CLASS_HUFFMAN_ONLY data at all. */ -+ (clas == Z_CLASS_STANDARD || (clas == Z_CLASS_COOKIE && -+ s->prev_length == input_length && -+ s->prev_match > 0 && -+ /* We require that a Z_CLASS_COOKIE match be -+ * preceded by either a semicolon (which cannot be -+ * part of a cookie), or non-cookie data. This is -+ * to prevent -+ * a cookie from being a prefix of another. -+ * spdy_framer.cc ensures that cookies are always -+ * terminated by a semicolon. */ -+ (class_at(s, s->prev_match-1) == Z_CLASS_STANDARD || -+ *(s->window + s->prev_match-1) == ';')))) { - uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - -diff --git a/third_party/zlib/deflate.h b/third_party/zlib/deflate.h -index cbf0d1e..83b4602 100644 ---- a/third_party/zlib/deflate.h -+++ b/third_party/zlib/deflate.h -@@ -91,6 +91,9 @@ typedef unsigned IPos; - * save space in the various tables. IPos is used only for parameter passing. - */ - -+#define Z_COOKIE_HASH_SIZE 64 -+#define Z_COOKIE_HASH_MASK (Z_COOKIE_HASH_SIZE-1) -+ - typedef struct internal_state { - z_streamp strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ -@@ -139,6 +142,8 @@ typedef struct internal_state { - uInt hash_mask; /* hash_size-1 */ - - uInt hash_shift; -+ Bytef *class_bitmap; /* bitmap of class for each byte in window */ -+ IPos cookie_locations[Z_COOKIE_HASH_SIZE]; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: -diff --git a/third_party/zlib/zlib.h b/third_party/zlib/zlib.h -index 4d54af9..da7e971 100644 ---- a/third_party/zlib/zlib.h -+++ b/third_party/zlib/zlib.h -@@ -101,6 +101,7 @@ typedef struct z_stream_s { - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -+ int clas; - } z_stream; - - typedef z_stream FAR *z_streamp; -@@ -207,6 +208,10 @@ typedef gz_header FAR *gz_headerp; - - #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -+#define Z_CLASS_STANDARD 0 -+#define Z_CLASS_COOKIE 1 -+#define Z_CLASS_HUFFMAN_ONLY 2 -+ - #define zlib_version zlibVersion() - /* for compatibility with versions < 1.0.2 */ - -@@ -1587,6 +1592,13 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); -+# else -+ ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); -+ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); -+ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); -+ ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); -+ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); -+ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); - # endif - #else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); diff --git a/third_party/zlib/zlib.gyp b/third_party/zlib/zlib.gyp index 73c4f43..4215f62 100644 --- a/third_party/zlib/zlib.gyp +++ b/third_party/zlib/zlib.gyp @@ -5,10 +5,12 @@ { 'variables': { 'conditions': [ - [ 'OS=="none"', { - # Because we have a patched zlib, we cannot use the system libz. + [ 'os_posix == 1 and OS != "mac" and OS != "openbsd"', { + # Link to system .so since we already use it due to GTK. + # TODO(pvalchev): OpenBSD is purposefully left out, as the system + # zlib brings up an incompatibility that breaks rendering. 'use_system_zlib%': 1, - }, { + }, { # os_posix != 1 or OS == "mac" or OS == "openbsd" 'use_system_zlib%': 0, }], ], @@ -68,8 +70,6 @@ 'sources!': [ 'contrib/minizip/iowin32.c' ], - }], ['OS=="android"', { - 'toolsets': ['target', 'host'], }], ], }, { diff --git a/third_party/zlib/zlib.h b/third_party/zlib/zlib.h index da7e971..4d54af9 100644 --- a/third_party/zlib/zlib.h +++ b/third_party/zlib/zlib.h @@ -101,7 +101,6 @@ typedef struct z_stream_s { int data_type; /* best guess about the data type: binary or text */ uLong adler; /* adler32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ - int clas; } z_stream; typedef z_stream FAR *z_streamp; @@ -208,10 +207,6 @@ typedef gz_header FAR *gz_headerp; #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ -#define Z_CLASS_STANDARD 0 -#define Z_CLASS_COOKIE 1 -#define Z_CLASS_HUFFMAN_ONLY 2 - #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ @@ -1592,13 +1587,6 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); -# else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); # endif #else ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); |