Skip to content

Commit 389d0f6

Browse files
zlib: restart format detection when resetting Unzip
Signed-off-by: marcopiraccini <marco.piraccini@gmail.com>
1 parent ea08334 commit 389d0f6

2 files changed

Lines changed: 54 additions & 2 deletions

File tree

‎src/node_zlib.cc‎

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,10 @@ class ZlibContext final : public MemoryRetainer {
189189
void SetFlush(int flush);
190190
void GetAfterWriteOffsets(uint32_t* avail_in, uint32_t* avail_out) const;
191191
CompressionError GetErrorInfo() const;
192-
inline void SetMode(node_zlib_mode mode) { mode_ = mode; }
192+
inline void SetMode(node_zlib_mode mode) {
193+
mode_ = mode;
194+
auto_detect_ = mode == UNZIP;
195+
}
193196
CompressionError ResetStream();
194197

195198
// Zlib-specific:
@@ -214,6 +217,7 @@ class ZlibContext final : public MemoryRetainer {
214217
private:
215218
CompressionError ErrorForMessage(const char* message) const;
216219
CompressionError SetDictionary();
220+
CompressionError ResetZStream();
217221
bool InitZlib();
218222

219223
Mutex mutex_; // Protects zlib_init_done_.
@@ -223,6 +227,7 @@ class ZlibContext final : public MemoryRetainer {
223227
int level_ = 0;
224228
int mem_level_ = 0;
225229
node_zlib_mode mode_ = NONE;
230+
bool auto_detect_ = false;
226231
int strategy_ = 0;
227232
int window_bits_ = 0;
228233
bool reject_garbage_after_end_ = false;
@@ -1168,7 +1173,7 @@ void ZlibContext::DoThreadPoolWork() {
11681173
// Trailing zero bytes are okay, though, since they are frequently
11691174
// used for padding.
11701175

1171-
ResetStream();
1176+
ResetZStream();
11721177
err_ = inflate(&strm_, flush_);
11731178
}
11741179
break;
@@ -1233,6 +1238,14 @@ CompressionError ZlibContext::GetErrorInfo() const {
12331238

12341239

12351240
CompressionError ZlibContext::ResetStream() {
1241+
if (auto_detect_) {
1242+
mode_ = UNZIP;
1243+
gzip_id_bytes_read_ = 0;
1244+
}
1245+
return ResetZStream();
1246+
}
1247+
1248+
CompressionError ZlibContext::ResetZStream() {
12361249
bool first_init_call = InitZlib();
12371250
if (first_init_call && err_ != Z_OK) {
12381251
return ErrorForMessage("Failed to init stream before reset");
@@ -1249,6 +1262,7 @@ CompressionError ZlibContext::ResetStream() {
12491262
case INFLATE:
12501263
case INFLATERAW:
12511264
case GUNZIP:
1265+
case UNZIP:
12521266
err_ = inflateReset(&strm_);
12531267
break;
12541268
default:
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict';
2+
3+
// Refs: https://github.com/nodejs/node/issues/64619
4+
5+
const common = require('../common');
6+
const assert = require('assert');
7+
const zlib = require('zlib');
8+
9+
function resetAfter(prefix, input, expected) {
10+
const chunks = [];
11+
const unzip = zlib.createUnzip();
12+
unzip.on('error', common.mustNotCall());
13+
unzip.on('data', (chunk) => chunks.push(chunk));
14+
unzip.on('end', common.mustCall(() => {
15+
assert.strictEqual(Buffer.concat(chunks).toString(), expected);
16+
}));
17+
unzip.write(prefix, common.mustCall(() => {
18+
unzip.reset();
19+
unzip.end(input);
20+
}));
21+
}
22+
23+
// Reset in the middle of the gzip magic number.
24+
resetAfter(Buffer.from([0x1f]), zlib.gzipSync('hello'), 'hello');
25+
26+
// Reset after deflate was detected.
27+
resetAfter(
28+
zlib.deflateSync('discarded').subarray(0, 2),
29+
Buffer.concat([zlib.gzipSync('abc'), zlib.gzipSync('def'), zlib.gzipSync('ghi')]),
30+
'abcdefghi',
31+
);
32+
33+
// Reset after gzip was detected.
34+
resetAfter(
35+
zlib.gzipSync('discarded').subarray(0, 4),
36+
zlib.deflateSync('hello'),
37+
'hello',
38+
);

0 commit comments

Comments
 (0)