Coverage Report

Created: 2025-11-24 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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/QPDFObjectHandle_private.hh>
9
#include <qpdf/QTC.hh>
10
11
bool
12
SF_FlateLzwDecode::setDecodeParms(QPDFObjectHandle decode_parms)
13
20.5k
{
14
20.5k
    if (decode_parms.null()) {
15
13.5k
        return true;
16
13.5k
    }
17
18
7.00k
    auto memory_limit = Pl_Flate::memory_limit();
19
20
7.00k
    std::set<std::string> keys = decode_parms.getKeys();
21
15.3k
    for (auto const& key: keys) {
22
15.3k
        QPDFObjectHandle value = decode_parms.getKey(key);
23
15.3k
        if (key == "/Predictor") {
24
3.74k
            if (value.isInteger()) {
25
3.72k
                predictor = value.getIntValueAsInt();
26
3.72k
                if (!(predictor == 1 || predictor == 2 || (predictor >= 10 && predictor <= 15))) {
27
89
                    return false;
28
89
                }
29
3.72k
            } else {
30
15
                return false;
31
15
            }
32
11.5k
        } else if (key == "/Columns" || key == "/Colors" || key == "/BitsPerComponent") {
33
3.12k
            if (value.isInteger()) {
34
3.11k
                int val = value.getIntValueAsInt();
35
3.11k
                if (memory_limit && static_cast<unsigned int>(val) > memory_limit) {
36
10
                    QPDFLogger::defaultLogger()->warn(
37
10
                        "SF_FlateLzwDecode parameter exceeds PL_Flate memory limit\n");
38
10
                    return false;
39
10
                }
40
3.10k
                if (key == "/Columns") {
41
1.36k
                    columns = val;
42
1.73k
                } else if (key == "/Colors") {
43
1.13k
                    colors = val;
44
1.13k
                } else if (key == "/BitsPerComponent") {
45
600
                    bits_per_component = val;
46
600
                }
47
3.10k
            } else {
48
10
                return false;
49
10
            }
50
8.44k
        } else if (lzw && (key == "/EarlyChange")) {
51
553
            if (value.isInteger()) {
52
550
                int earlychange = value.getIntValueAsInt();
53
550
                early_code_change = (earlychange == 1);
54
550
                if (!(earlychange == 0 || earlychange == 1)) {
55
40
                    return false;
56
40
                }
57
550
            } else {
58
3
                return false;
59
3
            }
60
553
        }
61
15.3k
    }
62
63
6.83k
    if (predictor > 1 && columns == 0) {
64
3
        return false;
65
3
    }
66
67
6.83k
    return true;
68
6.83k
}
69
70
Pipeline*
71
SF_FlateLzwDecode::getDecodePipeline(Pipeline* next)
72
20.3k
{
73
20.3k
    std::unique_ptr<Pipeline> pipeline;
74
20.3k
    if (predictor >= 10 && predictor <= 15) {
75
1.99k
        QTC::TC("qpdf", "SF_FlateLzwDecode PNG filter");
76
1.99k
        pipeline = std::make_unique<Pl_PNGFilter>(
77
1.99k
            "png decode",
78
1.99k
            next,
79
1.99k
            Pl_PNGFilter::a_decode,
80
1.99k
            QIntC::to_uint(columns),
81
1.99k
            QIntC::to_uint(colors),
82
1.99k
            QIntC::to_uint(bits_per_component));
83
1.99k
        next = pipeline.get();
84
1.99k
        pipelines.push_back(std::move(pipeline));
85
18.3k
    } else if (predictor == 2) {
86
1.42k
        QTC::TC("qpdf", "SF_FlateLzwDecode TIFF predictor");
87
1.42k
        pipeline = std::make_unique<Pl_TIFFPredictor>(
88
1.42k
            "tiff decode",
89
1.42k
            next,
90
1.42k
            Pl_TIFFPredictor::a_decode,
91
1.42k
            QIntC::to_uint(columns),
92
1.42k
            QIntC::to_uint(colors),
93
1.42k
            QIntC::to_uint(bits_per_component));
94
1.42k
        next = pipeline.get();
95
1.42k
        pipelines.push_back(std::move(pipeline));
96
1.42k
    }
97
98
20.3k
    if (lzw) {
99
5.97k
        pipeline = std::make_unique<Pl_LZWDecoder>("lzw decode", next, early_code_change);
100
14.3k
    } else {
101
14.3k
        pipeline = std::make_unique<Pl_Flate>("stream inflate", next, Pl_Flate::a_inflate);
102
14.3k
    }
103
20.3k
    next = pipeline.get();
104
20.3k
    pipelines.push_back(std::move(pipeline));
105
20.3k
    return next;
106
20.3k
}