Skip to content

Commit 0ddc6b7

Browse files
marcopiracciniaduh95
authored andcommitted
zlib: restart format detection when resetting Unzip
Signed-off-by: marcopiraccini <marco.piraccini@gmail.com> PR-URL: #66169 Fixes: #64619 Reviewed-By: Paolo Insogna <paolo@cowtech.it>
1 parent 94c0e06 commit 0ddc6b7

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

210213
// Zlib-specific:
@@ -229,6 +232,7 @@ class ZlibContext final : public MemoryRetainer {
229232
private:
230233
CompressionError ErrorForMessage(const char* message) const;
231234
CompressionError SetDictionary();
235+
CompressionError ResetZStream();
232236
bool InitZlib();
233237

234238
Mutex mutex_; // Protects zlib_init_done_.
@@ -238,6 +242,7 @@ class ZlibContext final : public MemoryRetainer {
238242
int level_ = 0;
239243
int mem_level_ = 0;
240244
node_zlib_mode mode_ = NONE;
245+
bool auto_detect_ = false;
241246
int strategy_ = 0;
242247
int window_bits_ = 0;
243248
bool reject_garbage_after_end_ = false;
@@ -1215,7 +1220,7 @@ void ZlibContext::DoThreadPoolWork() {
12151220
// Trailing zero bytes are okay, though, since they are frequently
12161221
// used for padding.
12171222

1218-
ResetStream();
1223+
ResetZStream();
12191224
err_ = inflate(&strm_, flush_);
12201225
}
12211226
break;
@@ -1294,6 +1299,14 @@ CompressionError ZlibContext::ResetStream() {
12941299
Z_STREAM_ERROR);
12951300
}
12961301

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