Coverage Report

Created: 2025-07-01 06:14

/src/qpdf/libqpdf/SF_FlateLzwDecode.cc
Line
Count
Source
1
#include <qpdf/SF_FlateLzwDecode.hh>
2
3
#include <qpdf/Pl_Flate.hh>
4
#include <qpdf/Pl_LZWDecoder.hh>
5
#include <qpdf/Pl_PNGFilter.hh>
6
#include <qpdf/Pl_TIFFPredictor.hh>
7
#include <qpdf/QIntC.hh>
8
#include <qpdf/QTC.hh>
9
10
bool
11
SF_FlateLzwDecode::setDecodeParms(QPDFObjectHandle decode_parms)
12
61.9k
{
13
61.9k
    if (decode_parms.isNull()) {
14
48.4k
        return true;
15
48.4k
    }
16
17
13.4k
    auto memory_limit = Pl_Flate::memory_limit();
18
19
13.4k
    std::set<std::string> keys = decode_parms.getKeys();
20
35.7k
    for (auto const& key: keys) {
21
35.7k
        QPDFObjectHandle value = decode_parms.getKey(key);
22
35.7k
        if (key == "/Predictor") {
23
8.57k
            if (value.isInteger()) {
24
8.54k
                predictor = value.getIntValueAsInt();
25
8.54k
                if (!(predictor == 1 || predictor == 2 || (predictor >= 10 && predictor <= 15))) {
26
289
                    return false;
27
289
                }
28
8.54k
            } else {
29
29
                return false;
30
29
            }
31
27.1k
        } else if (key == "/Columns" || key == "/Colors" || key == "/BitsPerComponent") {
32
12.1k
            if (value.isInteger()) {
33
12.1k
                int val = value.getIntValueAsInt();
34
12.1k
                if (memory_limit && static_cast<unsigned int>(val) > memory_limit) {
35
126
                    QPDFLogger::defaultLogger()->warn(
36
126
                        "SF_FlateLzwDecode parameter exceeds PL_Flate memory limit\n");
37
126
                    return false;
38
126
                }
39
12.0k
                if (key == "/Columns") {
40
6.89k
                    columns = val;
41
6.89k
                } else if (key == "/Colors") {
42
2.22k
                    colors = val;
43
2.89k
                } else if (key == "/BitsPerComponent") {
44
2.89k
                    bits_per_component = val;
45
2.89k
                }
46
12.0k
            } else {
47
52
                return false;
48
52
            }
49
14.9k
        } else if (lzw && (key == "/EarlyChange")) {
50
265
            if (value.isInteger()) {
51
243
                int earlychange = value.getIntValueAsInt();
52
243
                early_code_change = (earlychange == 1);
53
243
                if (!(earlychange == 0 || earlychange == 1)) {
54
67
                    return false;
55
67
                }
56
243
            } else {
57
22
                return false;
58
22
            }
59
265
        }
60
35.7k
    }
61
62
12.8k
    if (predictor > 1 && columns == 0) {
63
30
        return false;
64
30
    }
65
66
12.8k
    return true;
67
12.8k
}
68
69
Pipeline*
70
SF_FlateLzwDecode::getDecodePipeline(Pipeline* next)
71
60.7k
{
72
60.7k
    std::unique_ptr<Pipeline> pipeline;
73
60.7k
    if (predictor >= 10 && predictor <= 15) {
74
6.62k
        QTC::TC("qpdf", "SF_FlateLzwDecode PNG filter");
75
6.62k
        pipeline = std::make_unique<Pl_PNGFilter>(
76
6.62k
            "png decode",
77
6.62k
            next,
78
6.62k
            Pl_PNGFilter::a_decode,
79
6.62k
            QIntC::to_uint(columns),
80
6.62k
            QIntC::to_uint(colors),
81
6.62k
            QIntC::to_uint(bits_per_component));
82
6.62k
        next = pipeline.get();
83
6.62k
        pipelines.push_back(std::move(pipeline));
84
54.1k
    } else if (predictor == 2) {
85
1.43k
        QTC::TC("qpdf", "SF_FlateLzwDecode TIFF predictor");
86
1.43k
        pipeline = std::make_unique<Pl_TIFFPredictor>(
87
1.43k
            "tiff decode",
88
1.43k
            next,
89
1.43k
            Pl_TIFFPredictor::a_decode,
90
1.43k
            QIntC::to_uint(columns),
91
1.43k
            QIntC::to_uint(colors),
92
1.43k
            QIntC::to_uint(bits_per_component));
93
1.43k
        next = pipeline.get();
94
1.43k
        pipelines.push_back(std::move(pipeline));
95
1.43k
    }
96
97
60.7k
    if (lzw) {
98
6.24k
        pipeline = std::make_unique<Pl_LZWDecoder>("lzw decode", next, early_code_change);
99
54.5k
    } else {
100
54.5k
        pipeline = std::make_unique<Pl_Flate>("stream inflate", next, Pl_Flate::a_inflate);
101
54.5k
    }
102
60.7k
    next = pipeline.get();
103
60.7k
    pipelines.push_back(std::move(pipeline));
104
60.7k
    return next;
105
60.7k
}