Coverage Report

Created: 2026-02-10 07:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poppler/poppler/FlateEncoder.cc
Line
Count
Source
1
//========================================================================
2
//
3
// FlateEncoder.cc
4
//
5
// Copyright (C) 2016, William Bader <williambader@hotmail.com>
6
// Copyright (C) 2017 Adrian Johnson <ajohnson@redneon.com>
7
// Copyright (C) 2021 Even Rouault <even.rouault@spatialys.com>
8
// Copyright (C) 2022 Albert Astals Cid <aacid@kde.org>
9
// Copyright (C) 2025 Nelson Benítez León <nbenitezl@gmail.com>
10
// Copyright (C) 2025 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
11
// Copyright (C) 2025 Arnav V <arnav0872@gmail.com>
12
//
13
// This file is under the GPLv2 or later license
14
//
15
//========================================================================
16
17
#include <config.h>
18
19
#include "FlateEncoder.h"
20
21
//------------------------------------------------------------------------
22
// FlateEncoder
23
//------------------------------------------------------------------------
24
25
0
FlateEncoder::FlateEncoder(Stream *strA) : FilterStream(strA)
26
0
{
27
0
    int zlib_status;
28
29
0
    outBufPtr = outBufEnd = outBuf;
30
0
    inBufEof = outBufEof = false;
31
32
    // We used to assign Z_NULL to the 3 following members of zlib_stream,
33
    // but as Z_NULL is a #define to 0, using it triggers the
34
    // -Wzero-as-null-pointer-constant warning.
35
    // For safety, check that the Z_NULL definition is equivalent to
36
    // 0 / null pointer.
37
0
    static_assert(static_cast<int>(Z_NULL) == 0); // NOLINT(readability-redundant-casting)
38
0
    zlib_stream.zalloc = nullptr;
39
0
    zlib_stream.zfree = nullptr;
40
0
    zlib_stream.opaque = nullptr;
41
42
0
    zlib_status = deflateInit(&zlib_stream, Z_DEFAULT_COMPRESSION);
43
44
0
    if (zlib_status != Z_OK) {
45
0
        inBufEof = outBufEof = true;
46
0
        error(errInternal, -1, "Internal: deflateInit() failed in FlateEncoder::FlateEncoder()");
47
0
    }
48
49
0
    zlib_stream.next_out = outBufEnd;
50
0
    zlib_stream.avail_out = 1; /* anything but 0 to trigger a read */
51
0
}
52
53
FlateEncoder::~FlateEncoder()
54
0
{
55
0
    deflateEnd(&zlib_stream);
56
0
    if (str->isEncoder()) {
57
0
        delete str;
58
0
    }
59
0
}
60
61
bool FlateEncoder::rewind()
62
0
{
63
0
    int zlib_status;
64
65
0
    bool innerReset = str->rewind();
66
67
0
    outBufPtr = outBufEnd = outBuf;
68
0
    inBufEof = outBufEof = false;
69
70
0
    deflateEnd(&zlib_stream);
71
72
0
    zlib_status = deflateInit(&zlib_stream, Z_DEFAULT_COMPRESSION);
73
74
0
    if (zlib_status != Z_OK) {
75
0
        inBufEof = outBufEof = true;
76
0
        error(errInternal, -1, "Internal: deflateInit() failed in FlateEncoder::rewind()");
77
0
        return false;
78
0
    }
79
80
0
    zlib_stream.next_out = outBufEnd;
81
0
    zlib_stream.avail_out = 1; /* anything but 0 to trigger a read */
82
83
0
    return innerReset;
84
0
}
85
86
bool FlateEncoder::fillBuf()
87
0
{
88
0
    unsigned int starting_avail_out;
89
0
    int zlib_status;
90
91
    /* If the output is done, don't try to read more. */
92
93
0
    if (outBufEof) {
94
0
        return false;
95
0
    }
96
97
    /* The output buffer should be empty. */
98
    /* If it is not empty, push any processed data to the start. */
99
100
0
    if (outBufPtr > outBuf && outBufPtr < outBufEnd) {
101
0
        const ptrdiff_t n = outBufEnd - outBufPtr;
102
0
        memmove(outBuf, outBufPtr, n);
103
0
        outBufEnd = &outBuf[n];
104
0
    } else {
105
0
        outBufEnd = outBuf;
106
0
    }
107
0
    outBufPtr = outBuf;
108
109
    /* Keep feeding zlib until we get output. */
110
    /* zlib might consume a few input buffers */
111
    /* before it starts producing output. */
112
113
0
    do {
114
115
        /* avail_out > 0 means that zlib has depleted its input */
116
        /* and needs a new chunk of input in order to generate */
117
        /* more output. */
118
119
0
        if (zlib_stream.avail_out != 0) {
120
121
            /* Fill the input buffer */
122
123
0
            const int n = (inBufEof ? 0 : str->doGetChars(inBufSize, inBuf));
124
125
0
            if (n == 0) {
126
0
                inBufEof = true;
127
0
            }
128
129
0
            zlib_stream.next_in = inBuf;
130
0
            zlib_stream.avail_in = n;
131
0
        }
132
133
        /* Ask zlib for output. */
134
135
0
        zlib_stream.next_out = outBufEnd;
136
0
        starting_avail_out = static_cast<unsigned int>(&outBuf[outBufSize] - outBufEnd);
137
0
        zlib_stream.avail_out = starting_avail_out;
138
139
0
        zlib_status = deflate(&zlib_stream, (inBufEof ? Z_FINISH : Z_NO_FLUSH));
140
141
0
        if (zlib_status == Z_STREAM_ERROR || zlib_stream.avail_out > starting_avail_out) {
142
            /* Unrecoverable error */
143
0
            inBufEof = outBufEof = true;
144
0
            error(errInternal, -1, "Internal: deflate() failed in FlateEncoder::fillBuf()");
145
0
            return false;
146
0
        }
147
148
0
    } while (zlib_stream.avail_out == outBufSize && !inBufEof);
149
150
0
    outBufEnd = &outBuf[outBufSize] - zlib_stream.avail_out;
151
152
0
    if (inBufEof && zlib_stream.avail_out != 0) {
153
0
        outBufEof = true;
154
0
    }
155
156
0
    return outBufPtr < outBufEnd;
157
0
}