Coverage Report

Created: 2026-08-14 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/zeek/src/analyzer/protocol/zip/ZIP.cc
Line
Count
Source
1
// See the file "COPYING" in the main distribution directory for copyright.
2
3
#include "zeek/analyzer/protocol/zip/ZIP.h"
4
5
namespace zeek::analyzer::zip {
6
7
ZIP_Analyzer::ZIP_Analyzer(Connection* conn, bool orig, Method arg_method)
8
4.20k
    : analyzer::tcp::TCP_SupportAnalyzer("ZIP", conn, orig) {
9
4.20k
    zip = nullptr;
10
4.20k
    zip_status = Z_OK;
11
4.20k
    method = arg_method;
12
13
4.20k
    zip = new z_stream;
14
4.20k
    zip->zalloc = nullptr;
15
4.20k
    zip->zfree = nullptr;
16
4.20k
    zip->opaque = nullptr;
17
4.20k
    zip->next_out = nullptr;
18
4.20k
    zip->avail_out = 0;
19
4.20k
    zip->next_in = nullptr;
20
4.20k
    zip->avail_in = 0;
21
22
    // "32" is a gross overload hack that means "check it
23
    // for whether it's a gzip file".  Sheesh.
24
4.20k
    if ( inflateInit2(zip, MAX_WBITS + 32) != Z_OK ) {
25
0
        Weird("inflate_init_failed");
26
0
        delete zip;
27
0
        zip = nullptr;
28
0
    }
29
4.20k
}
30
31
4.20k
ZIP_Analyzer::~ZIP_Analyzer() { delete zip; }
32
33
4.20k
void ZIP_Analyzer::Done() {
34
4.20k
    Analyzer::Done();
35
36
4.20k
    if ( zip )
37
4.20k
        inflateEnd(zip);
38
4.20k
}
39
40
12.5k
void ZIP_Analyzer::DeliverStream(int len, const u_char* data, bool orig) {
41
12.5k
    analyzer::tcp::TCP_SupportAnalyzer::DeliverStream(len, data, orig);
42
43
12.5k
    if ( ! len || zip_status != Z_OK )
44
5.92k
        return;
45
46
6.67k
    static unsigned int unzip_size = 4096;
47
6.67k
    auto unzipbuf = std::make_unique<Bytef[]>(unzip_size);
48
49
6.67k
    int allow_restart = 1;
50
51
6.67k
    zip->next_in = reinterpret_cast<Bytef*>(const_cast<u_char*>(data));
52
6.67k
    zip->avail_in = len;
53
54
6.67k
    auto orig_next_in = zip->next_in;
55
6.67k
    size_t orig_avail_in = zip->avail_in;
56
57
11.9k
    while ( true ) {
58
11.9k
        zip->next_out = unzipbuf.get();
59
11.9k
        zip->avail_out = unzip_size;
60
61
11.9k
        zip_status = inflate(zip, Z_SYNC_FLUSH);
62
63
11.9k
        if ( zip_status == Z_STREAM_END || zip_status == Z_OK ) {
64
3.79k
            allow_restart = 0;
65
66
3.79k
            int have = unzip_size - zip->avail_out;
67
3.79k
            if ( have )
68
2.99k
                ForwardStream(have, unzipbuf.get(), IsOrig());
69
70
3.79k
            if ( zip_status == Z_STREAM_END ) {
71
274
                inflateEnd(zip);
72
274
                return;
73
274
            }
74
75
3.52k
            if ( zip->avail_in == 0 )
76
2.93k
                return;
77
3.52k
        }
78
79
8.10k
        else if ( allow_restart && zip_status == Z_DATA_ERROR ) {
80
            // Some servers seem to not generate zlib headers,
81
            // so this is an attempt to fix and continue anyway.
82
4.63k
            inflateEnd(zip);
83
84
4.63k
            if ( inflateInit2(zip, -MAX_WBITS) != Z_OK ) {
85
0
                Weird("inflate_init_failed");
86
0
                return;
87
0
            }
88
89
4.63k
            zip->next_in = orig_next_in;
90
4.63k
            zip->avail_in = orig_avail_in;
91
4.63k
            allow_restart = 0;
92
4.63k
            continue;
93
4.63k
        }
94
95
3.47k
        else {
96
3.47k
            Weird("inflate_failed");
97
3.47k
            return;
98
3.47k
        }
99
11.9k
    }
100
6.67k
}
101
102
} // namespace zeek::analyzer::zip