Coverage Report

Created: 2025-07-11 07:03

/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
73.4k
{
11
73.4k
    init();
12
73.4k
}
13
14
void
15
MD5::init()
16
73.4k
{
17
73.4k
    crypto = QPDFCryptoProvider::getImpl();
18
73.4k
    crypto->MD5_init();
19
73.4k
}
20
21
void
22
MD5::finalize()
23
0
{
24
0
    crypto->MD5_finalize();
25
0
}
26
27
void
28
MD5::reset()
29
0
{
30
0
    init();
31
0
}
32
33
void
34
MD5::encodeString(char const* str)
35
0
{
36
0
    size_t len = strlen(str);
37
0
    crypto->MD5_init();
38
0
    encodeDataIncrementally(str, len);
39
0
    crypto->MD5_finalize();
40
0
}
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::encodeFile(char const* filename, qpdf_offset_t up_to_offset)
50
0
{
51
0
    char buffer[1024];
52
53
0
    FILE* file = QUtil::safe_fopen(filename, "rb");
54
0
    size_t len;
55
0
    size_t so_far = 0;
56
0
    size_t to_try = 1024;
57
0
    size_t up_to_size = 0;
58
0
    if (up_to_offset >= 0) {
59
0
        up_to_size = QIntC::to_size(up_to_offset);
60
0
    }
61
0
    do {
62
0
        if ((up_to_offset >= 0) && ((so_far + to_try) > up_to_size)) {
63
0
            to_try = up_to_size - so_far;
64
0
        }
65
0
        len = fread(buffer, 1, to_try, file);
66
0
        if (len > 0) {
67
0
            encodeDataIncrementally(buffer, len);
68
0
            so_far += len;
69
0
            if ((up_to_offset >= 0) && (so_far >= up_to_size)) {
70
0
                break;
71
0
            }
72
0
        }
73
0
    } while (len > 0);
74
0
    if (ferror(file)) {
75
        // Assume, perhaps incorrectly, that errno was set by the underlying call to read....
76
0
        (void)fclose(file);
77
0
        QUtil::throw_system_error(std::string("MD5: read error on ") + filename);
78
0
    }
79
0
    (void)fclose(file);
80
81
0
    crypto->MD5_finalize();
82
0
}
83
84
void
85
MD5::digest(Digest result)
86
73.4k
{
87
73.4k
    crypto->MD5_finalize();
88
73.4k
    crypto->MD5_digest(result);
89
73.4k
}
90
91
std::string
92
MD5::digest()
93
662
{
94
662
    Digest digest_val;
95
662
    digest(digest_val);
96
662
    return {reinterpret_cast<char*>(digest_val), 16};
97
662
}
98
99
std::string
100
MD5::digest(std::string_view data)
101
5.91k
{
102
5.91k
    MD5 m;
103
5.91k
    m.encodeDataIncrementally(data.data(), data.size());
104
5.91k
    Digest digest_val;
105
5.91k
    m.digest(digest_val);
106
5.91k
    return {reinterpret_cast<char*>(digest_val), 16};
107
5.91k
}
108
109
void
110
MD5::print()
111
0
{
112
0
    Digest digest_val;
113
0
    digest(digest_val);
114
115
0
    unsigned int i;
116
0
    for (i = 0; i < 16; ++i) {
117
0
        printf("%02x", digest_val[i]);
118
0
    }
119
0
    printf("\n");
120
0
}
121
122
std::string
123
MD5::unparse()
124
0
{
125
0
    crypto->MD5_finalize();
126
0
    Digest digest_val;
127
0
    digest(digest_val);
128
0
    return QUtil::hex_encode(std::string(reinterpret_cast<char*>(digest_val), 16));
129
0
}
130
131
std::string
132
MD5::getDataChecksum(char const* buf, size_t len)
133
0
{
134
0
    MD5 m;
135
0
    m.encodeDataIncrementally(buf, len);
136
0
    return m.unparse();
137
0
}
138
139
std::string
140
MD5::getFileChecksum(char const* filename, qpdf_offset_t up_to_offset)
141
0
{
142
0
    MD5 m;
143
0
    m.encodeFile(filename, up_to_offset);
144
0
    return m.unparse();
145
0
}
146
147
bool
148
MD5::checkDataChecksum(char const* const checksum, char const* buf, size_t len)
149
0
{
150
0
    std::string actual_checksum = getDataChecksum(buf, len);
151
0
    return (checksum == actual_checksum);
152
0
}
153
154
bool
155
MD5::checkFileChecksum(char const* const checksum, char const* filename, qpdf_offset_t up_to_offset)
156
0
{
157
0
    bool result = false;
158
0
    try {
159
0
        std::string actual_checksum = getFileChecksum(filename, up_to_offset);
160
0
        result = (checksum == actual_checksum);
161
0
    } catch (std::runtime_error const&) {
162
        // Ignore -- return false
163
0
    }
164
0
    return result;
165
0
}