• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mavlink / MAVSDK / 10748697329

07 Sep 2024 04:40AM UTC coverage: 38.056% (-0.01%) from 38.066%
10748697329

Pull #2393

github

web-flow
Merge c49dfa278 into 6106bf78c
Pull Request #2393: CI: a few fixes and adding newer compilers

11448 of 30082 relevant lines covered (38.06%)

261.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/mavsdk/core/inflate_lzma.cpp
1

2
#include "inflate_lzma.h"
3

4
#include <cstdio>
5
#include <cstring>
6
#include <cerrno>
7
#define LZMA_API_STATIC
8
#include <lzma.h>
9

10
// The following code is from the liblzma example:
11
// https://github.com/tukaani-project/xz/blob/master/doc/examples/02_decompress.c
12
static bool init_decoder(lzma_stream* strm)
×
13
{
14
    // Initialize a .xz decoder. The decoder supports a memory usage limit
15
    // and a set of flags.
16
    //
17
    // The memory usage of the decompressor depends on the settings used
18
    // to compress a .xz file. It can vary from less than a megabyte to
19
    // a few gigabytes, but in practice (at least for now) it rarely
20
    // exceeds 65 MiB because that's how much memory is required to
21
    // decompress files created with "xz -9". Settings requiring more
22
    // memory take extra effort to use and don't (at least for now)
23
    // provide significantly better compression in most cases.
24
    //
25
    // Memory usage limit is useful if it is important that the
26
    // decompressor won't consume gigabytes of memory. The need
27
    // for limiting depends on the application. In this example,
28
    // no memory usage limiting is used. This is done by setting
29
    // the limit to UINT64_MAX.
30
    //
31
    // The .xz format allows concatenating compressed files as is:
32
    //
33
    //     echo foo | xz > foobar.xz
34
    //     echo bar | xz >> foobar.xz
35
    //
36
    // When decompressing normal standalone .xz files, LZMA_CONCATENATED
37
    // should always be used to support decompression of concatenated
38
    // .xz files. If LZMA_CONCATENATED isn't used, the decoder will stop
39
    // after the first .xz stream. This can be useful when .xz data has
40
    // been embedded inside another file format.
41
    //
42
    // Flags other than LZMA_CONCATENATED are supported too, and can
43
    // be combined with bitwise-or. See lzma/container.h
44
    // (src/liblzma/api/lzma/container.h in the source package or e.g.
45
    // /usr/include/lzma/container.h depending on the install prefix)
46
    // for details.
47
    lzma_ret ret = lzma_stream_decoder(strm, UINT64_MAX, LZMA_CONCATENATED);
×
48

49
    // Return successfully if the initialization went fine.
50
    if (ret == LZMA_OK)
×
51
        return true;
×
52

53
    // Something went wrong. The possible errors are documented in
54
    // lzma/container.h (src/liblzma/api/lzma/container.h in the source
55
    // package or e.g. /usr/include/lzma/container.h depending on the
56
    // install prefix).
57
    //
58
    // Note that LZMA_MEMLIMIT_ERROR is never possible here. If you
59
    // specify a very tiny limit, the error will be delayed until
60
    // the first headers have been parsed by a call to lzma_code().
61
    const char* msg;
62
    switch (ret) {
×
63
        case LZMA_MEM_ERROR:
×
64
            msg = "Memory allocation failed";
×
65
            break;
×
66

67
        case LZMA_OPTIONS_ERROR:
×
68
            msg = "Unsupported decompressor flags";
×
69
            break;
×
70

71
        default:
×
72
            // This is most likely LZMA_PROG_ERROR indicating a bug in
73
            // this program or in liblzma. It is inconvenient to have a
74
            // separate error message for errors that should be impossible
75
            // to occur, but knowing the error code is important for
76
            // debugging. That's why it is good to print the error code
77
            // at least when there is no good error message to show.
78
            msg = "Unknown error, possibly a bug";
×
79
            break;
×
80
    }
81

82
    fprintf(stderr, "Error initializing the decoder: %s (error code %u)\n", msg, ret);
×
83
    return false;
×
84
}
85

86
static bool decompress(lzma_stream* strm, const char* inname, FILE* infile, FILE* outfile)
×
87
{
88
    // When LZMA_CONCATENATED flag was used when initializing the decoder,
89
    // we need to tell lzma_code() when there will be no more input.
90
    // This is done by setting action to LZMA_FINISH instead of LZMA_RUN
91
    // in the same way as it is done when encoding.
92
    //
93
    // When LZMA_CONCATENATED isn't used, there is no need to use
94
    // LZMA_FINISH to tell when all the input has been read, but it
95
    // is still OK to use it if you want. When LZMA_CONCATENATED isn't
96
    // used, the decoder will stop after the first .xz stream. In that
97
    // case some unused data may be left in strm->next_in.
98
    lzma_action action = LZMA_RUN;
×
99

100
    uint8_t inbuf[BUFSIZ];
×
101
    uint8_t outbuf[BUFSIZ];
×
102

103
    strm->next_in = nullptr;
×
104
    strm->avail_in = 0;
×
105
    strm->next_out = outbuf;
×
106
    strm->avail_out = sizeof(outbuf);
×
107

108
    while (true) {
109
        if (strm->avail_in == 0 && !feof(infile)) {
×
110
            strm->next_in = inbuf;
×
111
            strm->avail_in = fread(inbuf, 1, sizeof(inbuf), infile);
×
112

113
            if (ferror(infile)) {
×
114
                fprintf(stderr, "%s: Read error: %s\n", inname, strerror(errno));
×
115
                // SonarCloud: Address of stack memory associated with local
116
                // variable 'inbuf' is still referred to by the stack variable
117
                // 'strm' upon returning to the caller. This will be a
118
                // dangling reference
119
                // Fixed by setting to nullptr.
120
                strm->next_in = nullptr;
×
121
                strm->avail_in = 0;
×
122
                strm->next_out = nullptr;
×
123
                strm->avail_out = 0;
×
124
                return false;
×
125
            }
126

127
            // Once the end of the input file has been reached,
128
            // we need to tell lzma_code() that no more input
129
            // will be coming. As said before, this isn't required
130
            // if the LZMA_CONCATENATED flag isn't used when
131
            // initializing the decoder.
132
            if (feof(infile))
×
133
                action = LZMA_FINISH;
×
134
        }
135

136
        lzma_ret ret = lzma_code(strm, action);
×
137

138
        if (strm->avail_out == 0 || ret == LZMA_STREAM_END) {
×
139
            size_t write_size = sizeof(outbuf) - strm->avail_out;
×
140

141
            if (fwrite(outbuf, 1, write_size, outfile) != write_size) {
×
142
                fprintf(stderr, "Write error: %s\n", strerror(errno));
×
143
                strm->next_in = nullptr;
×
144
                strm->avail_in = 0;
×
145
                strm->next_out = nullptr;
×
146
                strm->avail_out = 0;
×
147
                return false;
×
148
            }
149

150
            strm->next_out = outbuf;
×
151
            strm->avail_out = sizeof(outbuf);
×
152
        }
153

154
        if (ret != LZMA_OK) {
×
155
            // Once everything has been decoded successfully, the
156
            // return value of lzma_code() will be LZMA_STREAM_END.
157
            //
158
            // It is important to check for LZMA_STREAM_END. Do not
159
            // assume that getting ret != LZMA_OK would mean that
160
            // everything has gone well or that when you aren't
161
            // getting more output it must have successfully
162
            // decoded everything.
163
            if (ret == LZMA_STREAM_END) {
×
164
                strm->next_in = nullptr;
×
165
                strm->avail_in = 0;
×
166
                strm->next_out = nullptr;
×
167
                strm->avail_out = 0;
×
168
                return true;
×
169
            }
170

171
            // It's not LZMA_OK nor LZMA_STREAM_END,
172
            // so it must be an error code. See lzma/base.h
173
            // (src/liblzma/api/lzma/base.h in the source package
174
            // or e.g. /usr/include/lzma/base.h depending on the
175
            // install prefix) for the list and documentation of
176
            // possible values. Many values listen in lzma_ret
177
            // enumeration aren't possible in this example, but
178
            // can be made possible by enabling memory usage limit
179
            // or adding flags to the decoder initialization.
180
            const char* msg;
181
            switch (ret) {
×
182
                case LZMA_MEM_ERROR:
×
183
                    msg = "Memory allocation failed";
×
184
                    break;
×
185

186
                case LZMA_FORMAT_ERROR:
×
187
                    // .xz magic bytes weren't found.
188
                    msg = "The input is not in the .xz format";
×
189
                    break;
×
190

191
                case LZMA_OPTIONS_ERROR:
×
192
                    // For example, the headers specify a filter
193
                    // that isn't supported by this liblzma
194
                    // version (or it hasn't been enabled when
195
                    // building liblzma, but no-one sane does
196
                    // that unless building liblzma for an
197
                    // embedded system). Upgrading to a newer
198
                    // liblzma might help.
199
                    //
200
                    // Note that it is unlikely that the file has
201
                    // accidentally became corrupt if you get this
202
                    // error. The integrity of the .xz headers is
203
                    // always verified with a CRC32, so
204
                    // unintentionally corrupt files can be
205
                    // distinguished from unsupported files.
206
                    msg = "Unsupported compression options";
×
207
                    break;
×
208

209
                case LZMA_DATA_ERROR:
×
210
                    msg = "Compressed file is corrupt";
×
211
                    break;
×
212

213
                case LZMA_BUF_ERROR:
×
214
                    // Typically this error means that a valid
215
                    // file has got truncated, but it might also
216
                    // be a damaged part in the file that makes
217
                    // the decoder think the file is truncated.
218
                    // If you prefer, you can use the same error
219
                    // message for this as for LZMA_DATA_ERROR.
220
                    msg = "Compressed file is truncated or "
×
221
                          "otherwise corrupt";
222
                    break;
×
223

224
                default:
×
225
                    // This is most likely LZMA_PROG_ERROR.
226
                    msg = "Unknown error, possibly a bug";
×
227
                    break;
×
228
            }
229

230
            fprintf(
×
231
                stderr,
232
                "%s: Decoder error: "
233
                "%s (error code %u)\n",
234
                inname,
235
                msg,
236
                ret);
237

238
            strm->next_in = nullptr;
×
239
            strm->avail_in = 0;
×
240
            strm->next_out = nullptr;
×
241
            strm->avail_out = 0;
×
242
            return false;
×
243
        }
244
    }
×
245
}
246

247
bool InflateLZMA::inflateLZMAFile(
×
248
    const std::filesystem::path& lzma_filename, const std::filesystem::path& decompressed_filename)
249
{
250
    lzma_stream strm = LZMA_STREAM_INIT;
×
251

252
    if (!init_decoder(&strm)) {
×
253
        // Decoder initialization failed. There's no point
254
        // to retry it so we need to exit.
255
        return false;
×
256
    }
257

258
    FILE* infile = fopen(lzma_filename.string().c_str(), "rb");
×
259

260
    if (infile == nullptr) {
×
261
        fprintf(
×
262
            stderr,
263
            "%s: Error opening the "
264
            "input file: %s\n",
265
            lzma_filename.string().c_str(),
×
266
            strerror(errno));
×
267
        return false;
×
268
    }
269

270
    FILE* outfile = fopen(decompressed_filename.string().c_str(), "wb");
×
271

272
    if (outfile == nullptr) {
×
273
        fprintf(
×
274
            stderr,
275
            "%s: Error opening the "
276
            "output file: %s\n",
277
            decompressed_filename.string().c_str(),
×
278
            strerror(errno));
×
279
        fclose(infile);
×
280
        return false;
×
281
    }
282

283
    const bool success = decompress(&strm, lzma_filename.string().c_str(), infile, outfile);
×
284
    fclose(infile);
×
285
    fclose(outfile);
×
286

287
    lzma_end(&strm);
×
288

289
    return success;
×
290
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc