summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnna Henningsen <sqrt@entless.org>2016-03-24 02:13:09 +0100
committerBen Noordhuis <info@bnoordhuis.nl>2016-04-05 20:01:48 +0200
commit2d7e31614dbc61b4fd5a594649c12d65398a815e (patch)
treedcd3d252029a716e59ccf391c6f2a0bcddf99291 /src
parent0d41463d1f9498ee89b3cc706752a689b787db70 (diff)
downloadandroid-node-v8-2d7e31614dbc61b4fd5a594649c12d65398a815e.tar.gz
android-node-v8-2d7e31614dbc61b4fd5a594649c12d65398a815e.tar.bz2
android-node-v8-2d7e31614dbc61b4fd5a594649c12d65398a815e.zip
zlib: detect gzip files when using unzip*
Detect whether a gzip file is being passed to `unzip*` by testing the first bytes for the gzip magic bytes, and setting the decompression mode to `GUNZIP` or `INFLATE` according to the result. This enables gzip-only features like multi-member support to be used together with the `unzip*` autodetection support and thereby makes `gunzip*` and `unzip*` return identical results for gzip input again. Add a simple test for checking that features specific to `zlib.gunzip`, notably support for multiple members, also work when using `zlib.unzip`. PR-URL: https://github.com/nodejs/node/pull/5884 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/node_zlib.cc50
1 files changed, 49 insertions, 1 deletions
diff --git a/src/node_zlib.cc b/src/node_zlib.cc
index 4bf5cc76ba..aee1cbae95 100644
--- a/src/node_zlib.cc
+++ b/src/node_zlib.cc
@@ -68,7 +68,8 @@ class ZCtx : public AsyncWrap {
windowBits_(0),
write_in_progress_(false),
pending_close_(false),
- refs_(0) {
+ refs_(0),
+ gzip_id_bytes_read_(0) {
MakeWeak<ZCtx>(this);
}
@@ -225,6 +226,8 @@ class ZCtx : public AsyncWrap {
static void Process(uv_work_t* work_req) {
ZCtx *ctx = ContainerOf(&ZCtx::work_req_, work_req);
+ const Bytef* next_expected_header_byte = nullptr;
+
// If the avail_out is left at 0, then it means that it ran out
// of room. If there was avail_out left over, then it means
// that all of the input was consumed.
@@ -235,6 +238,50 @@ class ZCtx : public AsyncWrap {
ctx->err_ = deflate(&ctx->strm_, ctx->flush_);
break;
case UNZIP:
+ if (ctx->strm_.avail_in > 0) {
+ next_expected_header_byte = ctx->strm_.next_in;
+ }
+
+ switch (ctx->gzip_id_bytes_read_) {
+ case 0:
+ if (next_expected_header_byte == nullptr) {
+ break;
+ }
+
+ if (*next_expected_header_byte == GZIP_HEADER_ID1) {
+ ctx->gzip_id_bytes_read_ = 1;
+ next_expected_header_byte++;
+
+ if (ctx->strm_.avail_in == 1) {
+ // The only available byte was already read.
+ break;
+ }
+ } else {
+ ctx->mode_ = INFLATE;
+ break;
+ }
+
+ // fallthrough
+ case 1:
+ if (next_expected_header_byte == nullptr) {
+ break;
+ }
+
+ if (*next_expected_header_byte == GZIP_HEADER_ID2) {
+ ctx->gzip_id_bytes_read_ = 2;
+ ctx->mode_ = GUNZIP;
+ } else {
+ // There is no actual difference between INFLATE and INFLATERAW
+ // (after initialization).
+ ctx->mode_ = INFLATE;
+ }
+
+ break;
+ default:
+ CHECK(0 && "invalid number of gzip magic number bytes read");
+ }
+
+ // fallthrough
case INFLATE:
case GUNZIP:
case INFLATERAW:
@@ -591,6 +638,7 @@ class ZCtx : public AsyncWrap {
bool write_in_progress_;
bool pending_close_;
unsigned int refs_;
+ unsigned int gzip_id_bytes_read_;
};