77444 {
77445
77446 if (sd.refresh) {
77447 auto available =
static_cast<uint32_t>(sd.in_buff_end - sd.in_buff_start);
77448 if (available <= GZIP_FOOTER_SIZE) {
77449
77450 Close();
77451 return true;
77452 }
77453
77454 sd.refresh = false;
77455 auto body_ptr = sd.in_buff_start + GZIP_FOOTER_SIZE;
77456 uint8_t gzip_hdr[GZIP_HEADER_MINSIZE];
77457 memcpy(gzip_hdr, body_ptr, GZIP_HEADER_MINSIZE);
77459 body_ptr += GZIP_HEADER_MINSIZE;
77460 if (gzip_hdr[3] & GZIP_FLAG_EXTRA) {
77461 auto xlen = NumericCast<idx_t>((
uint8_t)*body_ptr | (
uint8_t) * (body_ptr + 1) << 8);
77462 body_ptr += xlen + 2;
77463 if (GZIP_FOOTER_SIZE + GZIP_HEADER_MINSIZE + 2 + xlen >= GZIP_HEADER_MAXSIZE) {
77464 throw InternalException("Extra field resulting in GZIP header larger than defined maximum (%d)",
77465 GZIP_HEADER_MAXSIZE);
77466 }
77467 }
77468 if (gzip_hdr[3] & GZIP_FLAG_NAME) {
77469 char c;
77470 do {
77471 c = UnsafeNumericCast<char>(*body_ptr);
77472 body_ptr++;
77473 } while (c != '\0' && body_ptr < sd.in_buff_end);
77474 if (static_cast<idx_t>(body_ptr - sd.in_buff_start) >= GZIP_HEADER_MAXSIZE) {
77475 throw InternalException("Filename resulting in GZIP header larger than defined maximum (%d)",
77476 GZIP_HEADER_MAXSIZE);
77477 }
77478 }
77479 sd.in_buff_start = body_ptr;
77480 if (sd.in_buff_end - sd.in_buff_start < 1) {
77481 Close();
77482 return true;
77483 }
77484 duckdb_miniz::mz_inflateEnd(mz_stream_ptr.get());
77485 auto sta = duckdb_miniz::mz_inflateInit2(mz_stream_ptr.get(), -MZ_DEFAULT_WINDOW_BITS);
77486 if (sta != duckdb_miniz::MZ_OK) {
77487 throw InternalException("Failed to initialize miniz");
77488 }
77489 }
77490
77491
77492 mz_stream_ptr->next_in = sd.in_buff_start;
77493 D_ASSERT(sd.in_buff_end - sd.in_buff_start < NumericLimits<int32_t>::Maximum());
77494 mz_stream_ptr->avail_in =
static_cast<uint32_t>(sd.in_buff_end - sd.in_buff_start);
77495 mz_stream_ptr->next_out = data_ptr_cast(sd.out_buff_end);
77496 mz_stream_ptr->avail_out =
static_cast<uint32_t>((sd.out_buff.get() + sd.out_buf_size) - sd.out_buff_end);
77497 auto ret = duckdb_miniz::mz_inflate(mz_stream_ptr.get(), duckdb_miniz::MZ_NO_FLUSH);
77498 if (ret != duckdb_miniz::MZ_OK && ret != duckdb_miniz::MZ_STREAM_END) {
77499 throw IOException("Failed to decode gzip stream: %s", duckdb_miniz::mz_error(ret));
77500 }
77501
77502 sd.in_buff_start = (data_ptr_t)mz_stream_ptr->next_in;
77503 sd.in_buff_end = sd.in_buff_start + mz_stream_ptr->avail_in;
77504 sd.out_buff_end = data_ptr_cast(mz_stream_ptr->next_out);
77505 D_ASSERT(sd.out_buff_end + mz_stream_ptr->avail_out == sd.out_buff.get() + sd.out_buf_size);
77506
77507
77508 if (ret == duckdb_miniz::MZ_STREAM_END) {
77509
77510 sd.refresh = true;
77511 }
77512 return false;
77513}