Coverage Report

Created: 2025-07-01 06:14

/src/qpdf/libqpdf/MD5.cc
Line
Count
Source (jump to first uncovered line)
1
#include <qpdf/MD5.hh>
2
3
#include <qpdf/QIntC.hh>
4
#include <qpdf/QPDFCryptoProvider.hh>
5
#include <qpdf/QUtil.hh>
6
7
#include <cstring>
8
9
MD5::MD5()
10
2.71M
{
11
2.71M
    init();
12
2.71M
}
13
14
void
15
MD5::init()
16
2.72M
{
17
2.72M
    this->crypto = QPDFCryptoProvider::getImpl();
18
2.72M
    this->crypto->MD5_init();
19
2.72M
}
20
21
void
22
MD5::finalize()
23
0
{
24
0
    this->crypto->MD5_finalize();
25
0
}
26
27
void
28
MD5::reset()
29
7.12k
{
30
7.12k
    init();
31
7.12k
}
32
33
void
34
MD5::encodeString(char const* str)
35
6.80k
{
36
6.80k
    size_t len = strlen(str);
37
6.80k
    crypto->MD5_init();
38
6.80k
    encodeDataIncrementally(str, len);
39
6.80k
    crypto->MD5_finalize();
40
6.80k
}
41
42
void
43
MD5::appendString(char const* input_string)
44
0
{
45
0
    encodeDataIncrementally(input_string, strlen(input_string));
46
0
}
47
48
void
49
MD5::encodeDataIncrementally(char const* data, size_t len)
50
5.40M
{
51
5.40M
    this->crypto->MD5_update(QUtil::unsigned_char_pointer(data), len);
52
5.40M
}
53
54
void
55
MD5::encodeFile(char const* filename, qpdf_offset_t up_to_offset)
56
0
{
57
0
    char buffer[1024];
58
59
0
    FILE* file = QUtil::safe_fopen(filename, "rb");
60
0
    size_t len;
61
0
    size_t so_far = 0;
62
0
    size_t to_try = 1024;
63
0
    size_t up_to_size = 0;
64
0
    if (up_to_offset >= 0) {
65
0
        up_to_size = QIntC::to_size(up_to_offset);
66
0
    }
67
0
    do {
68
0
        if ((up_to_offset >= 0) && ((so_far + to_try) > up_to_size)) {
69
0
            to_try = up_to_size - so_far;
70
0
        }
71
0
        len = fread(buffer, 1, to_try, file);
72
0
        if (len > 0) {
73
0
            encodeDataIncrementally(buffer, len);
74
0
            so_far += len;
75
0
            if ((up_to_offset >= 0) && (so_far >= up_to_size)) {
76
0
                break;
77
0
            }
78
0
        }
79
0
    } while (len > 0);
80
0
    if (ferror(file)) {
81
        // Assume, perhaps incorrectly, that errno was set by the underlying call to read....
82
0
        (void)fclose(file);
83
0
        QUtil::throw_system_error(std::string("MD5: read error on ") + filename);
84
0
    }
85
0
    (void)fclose(file);
86
87
0
    this->crypto->MD5_finalize();
88
0
}
89
90
void
91
MD5::digest(Digest result)
92
2.71M
{
93
2.71M
    this->crypto->MD5_finalize();
94
2.71M
    this->crypto->MD5_digest(result);
95
2.71M
}
96
97
void
98
MD5::print()
99
0
{
100
0
    Digest digest_val;
101
0
    digest(digest_val);
102
103
0
    unsigned int i;
104
0
    for (i = 0; i < 16; ++i) {
105
0
        printf("%02x", digest_val[i]);
106
0
    }
107
0
    printf("\n");
108
0
}
109
110
std::string
111
MD5::unparse()
112
6.80k
{
113
6.80k
    this->crypto->MD5_finalize();
114
6.80k
    Digest digest_val;
115
6.80k
    digest(digest_val);
116
6.80k
    return QUtil::hex_encode(std::string(reinterpret_cast<char*>(digest_val), 16));
117
6.80k
}
118
119
std::string
120
MD5::getDataChecksum(char const* buf, size_t len)
121
0
{
122
0
    MD5 m;
123
0
    m.encodeDataIncrementally(buf, len);
124
0
    return m.unparse();
125
0
}
126
127
std::string
128
MD5::getFileChecksum(char const* filename, qpdf_offset_t up_to_offset)
129
0
{
130
0
    MD5 m;
131
0
    m.encodeFile(filename, up_to_offset);
132
0
    return m.unparse();
133
0
}
134
135
bool
136
MD5::checkDataChecksum(char const* const checksum, char const* buf, size_t len)
137
0
{
138
0
    std::string actual_checksum = getDataChecksum(buf, len);
139
0
    return (checksum == actual_checksum);
140
0
}
141
142
bool
143
MD5::checkFileChecksum(char const* const checksum, char const* filename, qpdf_offset_t up_to_offset)
144
0
{
145
0
    bool result = false;
146
0
    try {
147
0
        std::string actual_checksum = getFileChecksum(filename, up_to_offset);
148
0
        result = (checksum == actual_checksum);
149
0
    } catch (std::runtime_error const&) {
150
        // Ignore -- return false
151
0
    }
152
0
    return result;
153
0
}