Skip to content

Commit c1557aa

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

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
@@ -203,7 +203,10 @@ class ZlibContext final : public MemoryRetainer {
203203
void SetFlush(int flush);
204204
void GetAfterWriteOffsets(uint32_t* avail_in, uint32_t* avail_out) const;
205205
CompressionError GetErrorInfo() const;
206-
inline void SetMode(node_zlib_mode mode) { mode_ = mode; }
206+
inline void SetMode(node_zlib_mode mode) {
207+
mode_ = mode;
208+
auto_detect_ = mode == UNZIP;
209+
}
207210
CompressionError ResetStream();
208211

209212
// Zlib-specific:
@@ -228,6 +231,7 @@ class ZlibContext final : public MemoryRetainer {
228231
private:
229232
CompressionError ErrorForMessage(const char* message) const;
230233
CompressionError SetDictionary();
234+
CompressionError ResetZStream();
231235
bool InitZlib();
232236

233237
Mutex mutex_; // Protects zlib_init_done_.
@@ -237,6 +241,7 @@ class ZlibContext final : public MemoryRetainer {
237241
int level_ = 0;
238242
int mem_level_ = 0;
239243
node_zlib_mode mode_ = NONE;
244+
bool auto_detect_ = false;
240245
int strategy_ = 0;
241246
int window_bits_ = 0;
242247
bool reject_garbage_after_end_ = false;
@@ -1214,7 +1219,7 @@ void ZlibContext::DoThreadPoolWork() {
12141219
// Trailing zero bytes are okay, though, since they are frequently
12151220
// used for padding.
12161221

1217-
ResetStream();
1222+
ResetZStream();
12181223
err_ = inflate(&strm_, flush_);
12191224
}
12201225
break;
@@ -1293,6 +1298,14 @@ CompressionError ZlibContext::ResetStream() {
12931298
Z_STREAM_ERROR);
12941299
}
12951300

1301+
if (auto_detect_) {
1302+
mode_ = UNZIP;
1303+
gzip_id_bytes_read_ = 0;
1304+
}
1305+
return ResetZStream();
1306+
}
1307+
1308+
CompressionError ZlibContext::ResetZStream() {
12961309
bool first_init_call = InitZlib();
12971310
if (first_init_call && err_ != Z_OK) {
12981311
return ErrorForMessage("Failed to init stream before reset");
@@ -1309,6 +1322,7 @@ CompressionError ZlibContext::ResetStream() {
13091322
case INFLATE:
13101323
case INFLATERAW:
13111324
case GUNZIP:
1325+
case UNZIP:
13121326
err_ = inflateReset(&strm_);
13131327
break;
13141328
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)