18 #include "tensorflow_serving/util/net_http/compression/gzip_zlib.h"
25 #include "absl/base/casts.h"
26 #include "absl/base/macros.h"
27 #include "tensorflow_serving/util/net_http/internal/net_logging.h"
29 namespace tensorflow {
47 constexpr
char GZIP_HEADER[] =
"\037\213\010\000\000\000\000\000\002\377";
48 constexpr uint8_t kMagicHeader[2] = {0x1f, 0x8b};
50 GZipHeader::Status GZipHeader::ReadMore(
const char *inbuf,
int inbuf_len,
51 const char **header_end) {
52 auto pos =
reinterpret_cast<const uint8_t *
>(inbuf);
53 const uint8_t *
const end = pos + inbuf_len;
58 if (*pos != kMagicHeader[0])
return INVALID_HEADER;
63 if (*pos != kMagicHeader[1])
return INVALID_HEADER;
68 if (*pos != Z_DEFLATED)
return INVALID_HEADER;
74 (*pos) & (FLAG_FHCRC | FLAG_FEXTRA | FLAG_FNAME | FLAG_FCOMMENT);
79 case IN_HEADER_MTIME_BYTE_0:
83 case IN_HEADER_MTIME_BYTE_1:
87 case IN_HEADER_MTIME_BYTE_2:
91 case IN_HEADER_MTIME_BYTE_3:
107 if (!(flags_ & FLAG_FEXTRA)) {
113 extra_length_ = *pos;
118 extra_length_ += (*pos) << 8;
121 ABSL_FALLTHROUGH_INTENDED;
128 const int num_extra_bytes =
129 std::min<int>(extra_length_, absl::implicit_cast<int>(end - pos));
130 pos += num_extra_bytes;
131 extra_length_ -= num_extra_bytes;
132 if (extra_length_ == 0) {
134 flags_ &= ~FLAG_FEXTRA;
140 if (!(flags_ & FLAG_FNAME)) {
141 state_ = IN_FCOMMENT;
145 pos =
reinterpret_cast<const uint8_t *
>(memchr(pos,
'\0', (end - pos)));
146 if (pos !=
nullptr) {
148 flags_ &= ~FLAG_FNAME;
149 state_ = IN_FCOMMENT;
156 if (!(flags_ & FLAG_FCOMMENT)) {
157 state_ = IN_FHCRC_BYTE_0;
161 pos =
reinterpret_cast<const uint8_t *
>(memchr(pos,
'\0', (end - pos)));
162 if (pos !=
nullptr) {
164 flags_ &= ~FLAG_FCOMMENT;
165 state_ = IN_FHCRC_BYTE_0;
171 case IN_FHCRC_BYTE_0:
172 if (!(flags_ & FLAG_FHCRC)) {
180 case IN_FHCRC_BYTE_1:
182 flags_ &= ~FLAG_FHCRC;
187 *header_end =
reinterpret_cast<const char *
>(pos);
188 return COMPLETE_HEADER;
195 if ((state_ > IN_HEADER_OS) && (flags_ == 0)) {
196 *header_end =
reinterpret_cast<const char *
>(pos);
197 return COMPLETE_HEADER;
199 return INCOMPLETE_HEADER;
204 : comp_init_(false), uncomp_init_(false), gzip_header_(new GZipHeader) {
206 init_settings_ = settings_;
211 deflateEnd(&comp_stream_);
214 inflateEnd(&uncomp_stream_);
219 void ZLib::Reinit() {
220 settings_.compression_level_ = Z_DEFAULT_COMPRESSION;
221 settings_.window_bits_ = MAX_WBITS;
222 settings_.mem_level_ = 8;
223 settings_.dont_hide_zstream_end_ =
false;
226 int err = deflateReset(&comp_stream_);
228 deflateEnd(&comp_stream_);
234 int wbits = -MAX_WBITS;
235 int err = inflateReset2(&uncomp_stream_, wbits);
237 inflateEnd(&uncomp_stream_);
238 uncomp_init_ =
false;
242 uncompressed_size_ = 0;
243 gzip_header_->Reset();
244 gzip_footer_bytes_ = -1;
250 gzip_header_->Reset();
253 void ZLib::SetDontHideStreamEnd() { settings_.dont_hide_zstream_end_ =
true; }
255 int ZLib::MinFooterSize()
const {
256 int min_footer_size = 2;
257 min_footer_size += 8;
258 return min_footer_size;
266 void ZLib::CompressErrorInit() {
268 deflateEnd(&comp_stream_);
275 int ZLib::WriteGzipHeader() {
276 if (comp_stream_.avail_out <
sizeof(GZIP_HEADER))
return Z_BUF_ERROR;
277 memcpy(comp_stream_.next_out, GZIP_HEADER,
sizeof(GZIP_HEADER) - 1);
278 comp_stream_.next_out +=
sizeof(GZIP_HEADER) - 1;
279 comp_stream_.avail_out -=
sizeof(GZIP_HEADER) - 1;
283 int ZLib::WriteGzipFooter(Bytef *dest, uLongf destLen) {
286 *dest++ = (crc_ >> 0) & 255;
287 *dest++ = (crc_ >> 8) & 255;
288 *dest++ = (crc_ >> 16) & 255;
289 *dest++ = (crc_ >> 24) & 255;
290 *dest++ = (uncompressed_size_ >> 0) & 255;
291 *dest++ = (uncompressed_size_ >> 8) & 255;
292 *dest++ = (uncompressed_size_ >> 16) & 255;
293 *dest++ = (uncompressed_size_ >> 24) & 255;
297 int ZLib::DeflateInit() {
298 int err = deflateInit2(&comp_stream_, settings_.compression_level_,
299 Z_DEFLATED, -settings_.window_bits_,
300 settings_.mem_level_, Z_DEFAULT_STRATEGY);
303 init_settings_.compression_level_ = settings_.compression_level_;
304 init_settings_.window_bits_ = settings_.window_bits_;
305 init_settings_.mem_level_ = settings_.mem_level_;
310 int ZLib::CompressInit(Bytef *dest, uLongf *destLen,
const Bytef *source,
314 comp_stream_.next_in = (Bytef *)source;
315 comp_stream_.avail_in = (uInt)*sourceLen;
317 if ((uLong)comp_stream_.avail_in != *sourceLen)
return Z_BUF_ERROR;
318 comp_stream_.next_out = dest;
319 comp_stream_.avail_out = (uInt)*destLen;
321 if ((uLong)comp_stream_.avail_out != *destLen)
return Z_BUF_ERROR;
327 if (comp_init_ && (init_settings_.window_bits_ != settings_.window_bits_ ||
328 init_settings_.mem_level_ != settings_.mem_level_)) {
329 deflateEnd(&comp_stream_);
335 err = deflateReset(&comp_stream_);
337 deflateEnd(&comp_stream_);
344 init_settings_.compression_level_ != settings_.compression_level_) {
345 err = deflateParams(&comp_stream_, settings_.compression_level_,
348 init_settings_.compression_level_ = settings_.compression_level_;
350 deflateEnd(&comp_stream_);
357 comp_stream_.zalloc = (alloc_func)0;
358 comp_stream_.zfree = (free_func)0;
359 comp_stream_.opaque = (voidpf)0;
361 if (err != Z_OK)
return err;
368 int ZLib::CompressAtMostOrAll(Bytef *dest, uLongf *destLen,
const Bytef *source,
373 if ((err = CompressInit(dest, destLen, source, sourceLen)) != Z_OK)
377 uint64_t compressed_size = comp_stream_.total_out;
381 if ((err = WriteGzipHeader()) != Z_OK)
return err;
382 compressed_size -=
sizeof(GZIP_HEADER) - 1;
383 crc_ = crc32(0,
nullptr, 0);
385 uncompressed_size_ = 0;
386 first_chunk_ =
false;
391 err = deflate(&comp_stream_, flush_mode);
393 const uLong source_bytes_consumed = *sourceLen - comp_stream_.avail_in;
394 *sourceLen = comp_stream_.avail_in;
396 if ((err == Z_STREAM_END || err == Z_OK) && comp_stream_.avail_in == 0 &&
397 comp_stream_.avail_out != 0) {
399 }
else if (err == Z_STREAM_END && comp_stream_.avail_in > 0) {
401 }
else if (err != Z_OK && err != Z_STREAM_END && err != Z_BUF_ERROR) {
405 }
else if (comp_stream_.avail_out == 0) {
409 assert(err == Z_OK || err == Z_STREAM_END || err == Z_BUF_ERROR);
410 if (err == Z_STREAM_END) err = Z_OK;
413 uncompressed_size_ += source_bytes_consumed;
414 compressed_size = comp_stream_.total_out - compressed_size;
415 *destLen = compressed_size;
417 crc_ = crc32(crc_, source, source_bytes_consumed);
422 int ZLib::CompressChunkOrAll(Bytef *dest, uLongf *destLen,
const Bytef *source,
426 CompressAtMostOrAll(dest, destLen, source, &sourceLen, flush_mode);
427 if (ret == Z_BUF_ERROR) CompressErrorInit();
431 int ZLib::CompressAtMost(Bytef *dest, uLongf *destLen,
const Bytef *source,
433 return CompressAtMostOrAll(dest, destLen, source, sourceLen, Z_SYNC_FLUSH);
438 int ZLib::CompressChunkDone(Bytef *dest, uLongf *destLen) {
440 if (*destLen <
static_cast<uLongf
>(MinFooterSize())) {
451 assert(!first_chunk_ && comp_init_);
453 const uLongf orig_destLen = *destLen;
454 if ((err = CompressChunkOrAll(dest, destLen, (
const Bytef *)&dummy, 0,
455 Z_FINISH)) != Z_OK) {
465 if ((err = WriteGzipFooter(dest + *destLen, orig_destLen - *destLen)) != Z_OK)
474 int ZLib::Compress(Bytef *dest, uLongf *destLen,
const Bytef *source,
477 const uLongf orig_destLen = *destLen;
478 if ((err = CompressChunkOrAll(dest, destLen, source, sourceLen, Z_FINISH)) !=
483 if ((err = WriteGzipFooter(dest + *destLen, orig_destLen - *destLen)) != Z_OK)
492 int ZLib::InflateInit() {
494 int wbits = (-MAX_WBITS);
495 int err = inflateInit2(&uncomp_stream_, wbits);
502 void ZLib::UncompressErrorInit() {
504 inflateEnd(&uncomp_stream_);
505 uncomp_init_ =
false;
510 int ZLib::UncompressInit(Bytef *dest, uLongf *destLen,
const Bytef *source,
514 uncomp_stream_.next_in = (Bytef *)source;
515 uncomp_stream_.avail_in = (uInt)*sourceLen;
517 if ((uLong)uncomp_stream_.avail_in != *sourceLen)
return Z_BUF_ERROR;
519 uncomp_stream_.next_out = dest;
520 uncomp_stream_.avail_out = (uInt)*destLen;
522 if ((uLong)uncomp_stream_.avail_out != *destLen)
return Z_BUF_ERROR;
530 int wbits = -MAX_WBITS;
531 err = inflateReset2(&uncomp_stream_, wbits);
533 UncompressErrorInit();
539 uncomp_stream_.zalloc = (alloc_func)0;
540 uncomp_stream_.zfree = (free_func)0;
541 uncomp_stream_.opaque = (voidpf)0;
543 if (err != Z_OK)
return err;
553 int ZLib::UncompressAtMostOrAll(Bytef *dest, uLongf *destLen,
554 const Bytef *source, uLong *sourceLen,
559 gzip_footer_bytes_ = -1;
564 const Bytef *bodyBegin =
nullptr;
565 GZipHeader::Status status = gzip_header_->ReadMore(
566 reinterpret_cast<const char *
>(source), *sourceLen,
567 reinterpret_cast<const char **
>(&bodyBegin));
569 case GZipHeader::INCOMPLETE_HEADER:
573 case GZipHeader::INVALID_HEADER:
576 case GZipHeader::COMPLETE_HEADER:
577 *sourceLen -= (bodyBegin - source);
579 crc_ = crc32(0,
nullptr, 0);
582 NET_LOG(FATAL,
"Unexpected gzip header parsing result: %d", status);
584 }
else if (gzip_footer_bytes_ >= 0) {
586 if (gzip_footer_bytes_ + *sourceLen >
sizeof(gzip_footer_)) {
590 uLong len =
sizeof(gzip_footer_) - gzip_footer_bytes_;
591 if (len > *sourceLen) len = *sourceLen;
593 memcpy(gzip_footer_ + gzip_footer_bytes_, source, len);
594 gzip_footer_bytes_ += len;
601 if ((err = UncompressInit(dest, destLen, source, sourceLen)) != Z_OK) {
603 "UncompressInit: Error: %d "
610 const uLong old_total_out = uncomp_stream_.total_out;
613 const uLong old_total_in = uncomp_stream_.total_in;
616 first_chunk_ =
false;
621 if (*sourceLen == 0) {
632 err = inflate(&uncomp_stream_, flush_mode);
635 const uLong bytes_read = uncomp_stream_.total_in - old_total_in;
636 assert((source + bytes_read) <= (source + *sourceLen));
637 *sourceLen = uncomp_stream_.avail_in;
642 if ((err == Z_STREAM_END) &&
643 ((gzip_footer_bytes_ == -1) ||
644 (
static_cast<size_t>(gzip_footer_bytes_) <
sizeof(gzip_footer_))) &&
645 (uncomp_stream_.avail_in <=
sizeof(gzip_footer_))) {
651 std::min(absl::implicit_cast<size_t>(uncomp_stream_.avail_in),
652 sizeof(gzip_footer_));
653 memcpy(gzip_footer_, source + bytes_read, gzip_footer_bytes_);
654 *sourceLen -= gzip_footer_bytes_;
655 }
else if ((err == Z_STREAM_END || err == Z_OK)
656 && uncomp_stream_.avail_in == 0) {
657 }
else if (err == Z_STREAM_END && uncomp_stream_.avail_in > 0) {
658 UncompressErrorInit();
660 }
else if (err != Z_OK && err != Z_STREAM_END && err != Z_BUF_ERROR) {
661 UncompressErrorInit();
663 }
else if (uncomp_stream_.avail_out == 0) {
667 assert(err == Z_OK || err == Z_BUF_ERROR || err == Z_STREAM_END);
668 if (err == Z_STREAM_END && !settings_.dont_hide_zstream_end_) err = Z_OK;
671 uncompressed_size_ = uncomp_stream_.total_out;
672 *destLen = uncomp_stream_.total_out - old_total_out;
674 crc_ = crc32(crc_, dest, *destLen);
679 int ZLib::UncompressChunkOrAll(Bytef *dest, uLongf *destLen,
680 const Bytef *source, uLong sourceLen,
683 UncompressAtMostOrAll(dest, destLen, source, &sourceLen, flush_mode);
684 if (ret == Z_BUF_ERROR) UncompressErrorInit();
688 int ZLib::UncompressAtMost(Bytef *dest, uLongf *destLen,
const Bytef *source,
690 return UncompressAtMostOrAll(dest, destLen, source, sourceLen, Z_SYNC_FLUSH);
697 bool ZLib::UncompressChunkDone() {
698 if (first_chunk_ || !uncomp_init_) {
704 Bytef dummyin, dummyout;
706 if (UncompressChunkOrAll(&dummyout, &dummylen, &dummyin, 0, Z_FINISH) !=
718 if ((gzip_footer_bytes_ != -1) && (gzip_footer_bytes_ != 0) &&
719 (
static_cast<size_t>(gzip_footer_bytes_) !=
sizeof(gzip_footer_)))
722 return IsGzipFooterValid();
725 bool ZLib::IsGzipFooterComplete()
const {
726 return gzip_footer_bytes_ != -1 &&
727 static_cast<size_t>(gzip_footer_bytes_) >=
sizeof(gzip_footer_);
730 bool ZLib::IsGzipFooterValid()
const {
731 if (!IsGzipFooterComplete())
return false;
734 uLong uncompressed_size = 0;
735 uncompressed_size +=
static_cast<uLong
>(gzip_footer_[7]) << 24;
736 uncompressed_size += gzip_footer_[6] << 16;
737 uncompressed_size += gzip_footer_[5] << 8;
738 uncompressed_size += gzip_footer_[4] << 0;
739 if (uncompressed_size != (uncompressed_size_ & 0xffffffff)) {
744 checksum +=
static_cast<uLong
>(gzip_footer_[3]) << 24;
745 checksum += gzip_footer_[2] << 16;
746 checksum += gzip_footer_[1] << 8;
747 checksum += gzip_footer_[0] << 0;
748 if (crc_ != checksum)
return false;
761 int ZLib::Uncompress(Bytef *dest, uLongf *destLen,
const Bytef *source,
764 if ((err = UncompressChunkOrAll(dest, destLen, source, sourceLen,
765 Z_FINISH)) != Z_OK) {
769 if (!UncompressChunkDone())
775 uLongf ZLib::GzipUncompressedLength(
const Bytef *source, uLong len) {
776 if (len <= 4)
return 0;
777 return (
static_cast<uLongf
>(source[len - 1]) << 24) +
778 (
static_cast<uLongf
>(source[len - 2]) << 16) +
779 (
static_cast<uLongf
>(source[len - 3]) << 8) +
780 (
static_cast<uLongf
>(source[len - 4]) << 0);
783 int ZLib::UncompressGzipAndAllocate(Bytef **dest, uLongf *destLen,
784 const Bytef *source, uLong sourceLen) {
787 uLongf uncompress_length = GzipUncompressedLength(source, sourceLen);
790 if (uncompress_length > *destLen) {
791 if (!HasGzipHeader(
reinterpret_cast<const char *
>(source), sourceLen)) {
797 *destLen = uncompress_length;
799 *dest = std::allocator<Bytef>().allocate(*destLen);
800 if (*dest ==
nullptr) {
804 const int retval = Uncompress(*dest, destLen, source, sourceLen);
805 if (retval != Z_OK) {
806 std::allocator<Bytef>().deallocate(*dest, *destLen);
813 bool ZLib::HasGzipHeader(
const char *source,
int sourceLen) {
815 const char *ptr =
nullptr;
816 return gzh.ReadMore(source, sourceLen, &ptr) == GZipHeader::COMPLETE_HEADER;