/src/CMake/Utilities/cmliblzma/liblzma/common/common.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: 0BSD |
2 | | |
3 | | /////////////////////////////////////////////////////////////////////////////// |
4 | | // |
5 | | /// \file common.c |
6 | | /// \brief Common functions needed in many places in liblzma |
7 | | // |
8 | | // Author: Lasse Collin |
9 | | // |
10 | | /////////////////////////////////////////////////////////////////////////////// |
11 | | |
12 | | #include "common.h" |
13 | | |
14 | | |
15 | | ///////////// |
16 | | // Version // |
17 | | ///////////// |
18 | | |
19 | | extern LZMA_API(uint32_t) |
20 | | lzma_version_number(void) |
21 | 0 | { |
22 | 0 | return LZMA_VERSION; |
23 | 0 | } |
24 | | |
25 | | |
26 | | extern LZMA_API(const char *) |
27 | | lzma_version_string(void) |
28 | 0 | { |
29 | 0 | return LZMA_VERSION_STRING; |
30 | 0 | } |
31 | | |
32 | | |
33 | | /////////////////////// |
34 | | // Memory allocation // |
35 | | /////////////////////// |
36 | | |
37 | | lzma_attr_alloc_size(1) |
38 | | extern void * |
39 | | lzma_alloc(size_t size, const lzma_allocator *allocator) |
40 | 19.8k | { |
41 | | // Some malloc() variants return NULL if called with size == 0. |
42 | 19.8k | if (size == 0) |
43 | 0 | size = 1; |
44 | | |
45 | 19.8k | void *ptr; |
46 | | |
47 | 19.8k | if (allocator != NULL && allocator->alloc != NULL) |
48 | 0 | ptr = allocator->alloc(allocator->opaque, 1, size); |
49 | 19.8k | else |
50 | 19.8k | ptr = malloc(size); |
51 | | |
52 | 19.8k | return ptr; |
53 | 19.8k | } |
54 | | |
55 | | |
56 | | lzma_attr_alloc_size(1) |
57 | | extern void * |
58 | | lzma_alloc_zero(size_t size, const lzma_allocator *allocator) |
59 | 0 | { |
60 | | // Some calloc() variants return NULL if called with size == 0. |
61 | 0 | if (size == 0) |
62 | 0 | size = 1; |
63 | |
|
64 | 0 | void *ptr; |
65 | |
|
66 | 0 | if (allocator != NULL && allocator->alloc != NULL) { |
67 | 0 | ptr = allocator->alloc(allocator->opaque, 1, size); |
68 | 0 | if (ptr != NULL) |
69 | 0 | memzero(ptr, size); |
70 | 0 | } else { |
71 | 0 | ptr = calloc(1, size); |
72 | 0 | } |
73 | |
|
74 | 0 | return ptr; |
75 | 0 | } |
76 | | |
77 | | |
78 | | extern void |
79 | | lzma_free(void *ptr, const lzma_allocator *allocator) |
80 | 20.9k | { |
81 | 20.9k | if (allocator != NULL && allocator->free != NULL) |
82 | 0 | allocator->free(allocator->opaque, ptr); |
83 | 20.9k | else |
84 | 20.9k | free(ptr); |
85 | | |
86 | 20.9k | return; |
87 | 20.9k | } |
88 | | |
89 | | |
90 | | ////////// |
91 | | // Misc // |
92 | | ////////// |
93 | | |
94 | | extern size_t |
95 | | lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, |
96 | | size_t in_size, uint8_t *restrict out, |
97 | | size_t *restrict out_pos, size_t out_size) |
98 | 1.58k | { |
99 | 1.58k | const size_t in_avail = in_size - *in_pos; |
100 | 1.58k | const size_t out_avail = out_size - *out_pos; |
101 | 1.58k | const size_t copy_size = my_min(in_avail, out_avail); |
102 | | |
103 | | // Call memcpy() only if there is something to copy. If there is |
104 | | // nothing to copy, in or out might be NULL and then the memcpy() |
105 | | // call would trigger undefined behavior. |
106 | 1.58k | if (copy_size > 0) |
107 | 1.51k | memcpy(out + *out_pos, in + *in_pos, copy_size); |
108 | | |
109 | 1.58k | *in_pos += copy_size; |
110 | 1.58k | *out_pos += copy_size; |
111 | | |
112 | 1.58k | return copy_size; |
113 | 1.58k | } |
114 | | |
115 | | |
116 | | extern lzma_ret |
117 | | lzma_next_filter_init(lzma_next_coder *next, const lzma_allocator *allocator, |
118 | | const lzma_filter_info *filters) |
119 | 6.84k | { |
120 | 6.84k | lzma_next_coder_init(filters[0].init, next, allocator); |
121 | 6.84k | next->id = filters[0].id; |
122 | 6.84k | return filters[0].init == NULL |
123 | 6.84k | ? LZMA_OK : filters[0].init(next, allocator, filters); |
124 | 6.84k | } |
125 | | |
126 | | |
127 | | extern lzma_ret |
128 | | lzma_next_filter_update(lzma_next_coder *next, const lzma_allocator *allocator, |
129 | | const lzma_filter *reversed_filters) |
130 | 0 | { |
131 | | // Check that the application isn't trying to change the Filter ID. |
132 | | // End of filters is indicated with LZMA_VLI_UNKNOWN in both |
133 | | // reversed_filters[0].id and next->id. |
134 | 0 | if (reversed_filters[0].id != next->id) |
135 | 0 | return LZMA_PROG_ERROR; |
136 | | |
137 | 0 | if (reversed_filters[0].id == LZMA_VLI_UNKNOWN) |
138 | 0 | return LZMA_OK; |
139 | | |
140 | 0 | assert(next->update != NULL); |
141 | 0 | return next->update(next->coder, allocator, NULL, reversed_filters); |
142 | 0 | } |
143 | | |
144 | | |
145 | | extern void |
146 | | lzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator) |
147 | 13.8k | { |
148 | 13.8k | if (next->init != (uintptr_t)(NULL)) { |
149 | | // To avoid tiny end functions that simply call |
150 | | // lzma_free(coder, allocator), we allow leaving next->end |
151 | | // NULL and call lzma_free() here. |
152 | 4.93k | if (next->end != NULL) |
153 | 4.93k | next->end(next->coder, allocator); |
154 | 0 | else |
155 | 0 | lzma_free(next->coder, allocator); |
156 | | |
157 | | // Reset the variables so the we don't accidentally think |
158 | | // that it is an already initialized coder. |
159 | 4.93k | *next = LZMA_NEXT_CODER_INIT; |
160 | 4.93k | } |
161 | | |
162 | 13.8k | return; |
163 | 13.8k | } |
164 | | |
165 | | |
166 | | ////////////////////////////////////// |
167 | | // External to internal API wrapper // |
168 | | ////////////////////////////////////// |
169 | | |
170 | | extern lzma_ret |
171 | | lzma_strm_init(lzma_stream *strm) |
172 | 4.00k | { |
173 | 4.00k | if (strm == NULL) |
174 | 0 | return LZMA_PROG_ERROR; |
175 | | |
176 | 4.00k | if (strm->internal == NULL) { |
177 | 4.00k | strm->internal = lzma_alloc(sizeof(lzma_internal), |
178 | 4.00k | strm->allocator); |
179 | 4.00k | if (strm->internal == NULL) |
180 | 0 | return LZMA_MEM_ERROR; |
181 | | |
182 | 4.00k | strm->internal->next = LZMA_NEXT_CODER_INIT; |
183 | 4.00k | } |
184 | | |
185 | 4.00k | memzero(strm->internal->supported_actions, |
186 | 4.00k | sizeof(strm->internal->supported_actions)); |
187 | 4.00k | strm->internal->sequence = ISEQ_RUN; |
188 | 4.00k | strm->internal->allow_buf_error = false; |
189 | | |
190 | 4.00k | strm->total_in = 0; |
191 | 4.00k | strm->total_out = 0; |
192 | | |
193 | 4.00k | return LZMA_OK; |
194 | 4.00k | } |
195 | | |
196 | | |
197 | | extern LZMA_API(lzma_ret) |
198 | | lzma_code(lzma_stream *strm, lzma_action action) |
199 | 8.03k | { |
200 | | // Sanity checks |
201 | 8.03k | if ((strm->next_in == NULL && strm->avail_in != 0) |
202 | 8.03k | || (strm->next_out == NULL && strm->avail_out != 0) |
203 | 8.03k | || strm->internal == NULL |
204 | 8.03k | || strm->internal->next.code == NULL |
205 | 8.03k | || (unsigned int)(action) > LZMA_ACTION_MAX |
206 | 8.03k | || !strm->internal->supported_actions[action]) |
207 | 0 | return LZMA_PROG_ERROR; |
208 | | |
209 | | // Check if unsupported members have been set to non-zero or non-NULL, |
210 | | // which would indicate that some new feature is wanted. |
211 | 8.03k | if (strm->reserved_ptr1 != NULL |
212 | 8.03k | || strm->reserved_ptr2 != NULL |
213 | 8.03k | || strm->reserved_ptr3 != NULL |
214 | 8.03k | || strm->reserved_ptr4 != NULL |
215 | 8.03k | || strm->reserved_int2 != 0 |
216 | 8.03k | || strm->reserved_int3 != 0 |
217 | 8.03k | || strm->reserved_int4 != 0 |
218 | 8.03k | || strm->reserved_enum1 != LZMA_RESERVED_ENUM |
219 | 8.03k | || strm->reserved_enum2 != LZMA_RESERVED_ENUM) |
220 | 0 | return LZMA_OPTIONS_ERROR; |
221 | | |
222 | 8.03k | switch (strm->internal->sequence) { |
223 | 6.25k | case ISEQ_RUN: |
224 | 6.25k | switch (action) { |
225 | 4.47k | case LZMA_RUN: |
226 | 4.47k | break; |
227 | | |
228 | 0 | case LZMA_SYNC_FLUSH: |
229 | 0 | strm->internal->sequence = ISEQ_SYNC_FLUSH; |
230 | 0 | break; |
231 | | |
232 | 0 | case LZMA_FULL_FLUSH: |
233 | 0 | strm->internal->sequence = ISEQ_FULL_FLUSH; |
234 | 0 | break; |
235 | | |
236 | 1.77k | case LZMA_FINISH: |
237 | 1.77k | strm->internal->sequence = ISEQ_FINISH; |
238 | 1.77k | break; |
239 | | |
240 | 0 | case LZMA_FULL_BARRIER: |
241 | 0 | strm->internal->sequence = ISEQ_FULL_BARRIER; |
242 | 0 | break; |
243 | 6.25k | } |
244 | | |
245 | 6.25k | break; |
246 | | |
247 | 6.25k | case ISEQ_SYNC_FLUSH: |
248 | | // The same action must be used until we return |
249 | | // LZMA_STREAM_END, and the amount of input must not change. |
250 | 0 | if (action != LZMA_SYNC_FLUSH |
251 | 0 | || strm->internal->avail_in != strm->avail_in) |
252 | 0 | return LZMA_PROG_ERROR; |
253 | | |
254 | 0 | break; |
255 | | |
256 | 0 | case ISEQ_FULL_FLUSH: |
257 | 0 | if (action != LZMA_FULL_FLUSH |
258 | 0 | || strm->internal->avail_in != strm->avail_in) |
259 | 0 | return LZMA_PROG_ERROR; |
260 | | |
261 | 0 | break; |
262 | | |
263 | 1.78k | case ISEQ_FINISH: |
264 | 1.78k | if (action != LZMA_FINISH |
265 | 1.78k | || strm->internal->avail_in != strm->avail_in) |
266 | 0 | return LZMA_PROG_ERROR; |
267 | | |
268 | 1.78k | break; |
269 | | |
270 | 1.78k | case ISEQ_FULL_BARRIER: |
271 | 0 | if (action != LZMA_FULL_BARRIER |
272 | 0 | || strm->internal->avail_in != strm->avail_in) |
273 | 0 | return LZMA_PROG_ERROR; |
274 | | |
275 | 0 | break; |
276 | | |
277 | 0 | case ISEQ_END: |
278 | 0 | return LZMA_STREAM_END; |
279 | | |
280 | 0 | case ISEQ_ERROR: |
281 | 0 | default: |
282 | 0 | return LZMA_PROG_ERROR; |
283 | 8.03k | } |
284 | | |
285 | 8.03k | size_t in_pos = 0; |
286 | 8.03k | size_t out_pos = 0; |
287 | 8.03k | lzma_ret ret = strm->internal->next.code( |
288 | 8.03k | strm->internal->next.coder, strm->allocator, |
289 | 8.03k | strm->next_in, &in_pos, strm->avail_in, |
290 | 8.03k | strm->next_out, &out_pos, strm->avail_out, action); |
291 | | |
292 | | // Updating next_in and next_out has to be skipped when they are NULL |
293 | | // to avoid null pointer + 0 (undefined behavior). Do this by checking |
294 | | // in_pos > 0 and out_pos > 0 because this way NULL + non-zero (a bug) |
295 | | // will get caught one way or other. |
296 | 8.03k | if (in_pos > 0) { |
297 | 4.34k | strm->next_in += in_pos; |
298 | 4.34k | strm->avail_in -= in_pos; |
299 | 4.34k | strm->total_in += in_pos; |
300 | 4.34k | } |
301 | | |
302 | 8.03k | if (out_pos > 0) { |
303 | 3.48k | strm->next_out += out_pos; |
304 | 3.48k | strm->avail_out -= out_pos; |
305 | 3.48k | strm->total_out += out_pos; |
306 | 3.48k | } |
307 | | |
308 | 8.03k | strm->internal->avail_in = strm->avail_in; |
309 | | |
310 | 8.03k | switch (ret) { |
311 | 5.89k | case LZMA_OK: |
312 | | // Don't return LZMA_BUF_ERROR when it happens the first time. |
313 | | // This is to avoid returning LZMA_BUF_ERROR when avail_out |
314 | | // was zero but still there was no more data left to written |
315 | | // to next_out. |
316 | 5.89k | if (out_pos == 0 && in_pos == 0) { |
317 | 3.62k | if (strm->internal->allow_buf_error) |
318 | 1.81k | ret = LZMA_BUF_ERROR; |
319 | 1.81k | else |
320 | 1.81k | strm->internal->allow_buf_error = true; |
321 | 3.62k | } else { |
322 | 2.26k | strm->internal->allow_buf_error = false; |
323 | 2.26k | } |
324 | 5.89k | break; |
325 | | |
326 | 0 | case LZMA_TIMED_OUT: |
327 | 0 | strm->internal->allow_buf_error = false; |
328 | 0 | ret = LZMA_OK; |
329 | 0 | break; |
330 | | |
331 | 0 | case LZMA_SEEK_NEEDED: |
332 | 0 | strm->internal->allow_buf_error = false; |
333 | | |
334 | | // If LZMA_FINISH was used, reset it back to the |
335 | | // LZMA_RUN-based state so that new input can be supplied |
336 | | // by the application. |
337 | 0 | if (strm->internal->sequence == ISEQ_FINISH) |
338 | 0 | strm->internal->sequence = ISEQ_RUN; |
339 | |
|
340 | 0 | break; |
341 | | |
342 | 28 | case LZMA_STREAM_END: |
343 | 28 | if (strm->internal->sequence == ISEQ_SYNC_FLUSH |
344 | 28 | || strm->internal->sequence == ISEQ_FULL_FLUSH |
345 | 28 | || strm->internal->sequence |
346 | 28 | == ISEQ_FULL_BARRIER) |
347 | 0 | strm->internal->sequence = ISEQ_RUN; |
348 | 28 | else |
349 | 28 | strm->internal->sequence = ISEQ_END; |
350 | | |
351 | | // Fall through |
352 | | |
353 | 28 | case LZMA_NO_CHECK: |
354 | 28 | case LZMA_UNSUPPORTED_CHECK: |
355 | 28 | case LZMA_GET_CHECK: |
356 | 28 | case LZMA_MEMLIMIT_ERROR: |
357 | | // Something else than LZMA_OK, but not a fatal error, |
358 | | // that is, coding may be continued (except if ISEQ_END). |
359 | 28 | strm->internal->allow_buf_error = false; |
360 | 28 | break; |
361 | | |
362 | 2.11k | default: |
363 | | // All the other errors are fatal; coding cannot be continued. |
364 | 2.11k | assert(ret != LZMA_BUF_ERROR); |
365 | 2.11k | strm->internal->sequence = ISEQ_ERROR; |
366 | 2.11k | break; |
367 | 8.03k | } |
368 | | |
369 | 8.03k | return ret; |
370 | 8.03k | } |
371 | | |
372 | | |
373 | | extern LZMA_API(void) |
374 | | lzma_end(lzma_stream *strm) |
375 | 4.00k | { |
376 | 4.00k | if (strm != NULL && strm->internal != NULL) { |
377 | 4.00k | lzma_next_end(&strm->internal->next, strm->allocator); |
378 | 4.00k | lzma_free(strm->internal, strm->allocator); |
379 | 4.00k | strm->internal = NULL; |
380 | 4.00k | } |
381 | | |
382 | 4.00k | return; |
383 | 4.00k | } |
384 | | |
385 | | |
386 | | #ifdef HAVE_SYMBOL_VERSIONS_LINUX |
387 | | // This is for compatibility with binaries linked against liblzma that |
388 | | // has been patched with xz-5.2.2-compat-libs.patch from RHEL/CentOS 7. |
389 | | LZMA_SYMVER_API("lzma_get_progress@XZ_5.2.2", |
390 | | void, lzma_get_progress_522)(lzma_stream *strm, |
391 | | uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow |
392 | | __attribute__((__alias__("lzma_get_progress_52"))); |
393 | | |
394 | | LZMA_SYMVER_API("lzma_get_progress@@XZ_5.2", |
395 | | void, lzma_get_progress_52)(lzma_stream *strm, |
396 | | uint64_t *progress_in, uint64_t *progress_out) lzma_nothrow; |
397 | | |
398 | | #define lzma_get_progress lzma_get_progress_52 |
399 | | #endif |
400 | | extern LZMA_API(void) |
401 | | lzma_get_progress(lzma_stream *strm, |
402 | | uint64_t *progress_in, uint64_t *progress_out) |
403 | 0 | { |
404 | 0 | if (strm->internal->next.get_progress != NULL) { |
405 | 0 | strm->internal->next.get_progress(strm->internal->next.coder, |
406 | 0 | progress_in, progress_out); |
407 | 0 | } else { |
408 | 0 | *progress_in = strm->total_in; |
409 | 0 | *progress_out = strm->total_out; |
410 | 0 | } |
411 | |
|
412 | 0 | return; |
413 | 0 | } |
414 | | |
415 | | |
416 | | extern LZMA_API(lzma_check) |
417 | | lzma_get_check(const lzma_stream *strm) |
418 | 0 | { |
419 | | // Return LZMA_CHECK_NONE if we cannot know the check type. |
420 | | // It's a bug in the application if this happens. |
421 | 0 | if (strm->internal->next.get_check == NULL) |
422 | 0 | return LZMA_CHECK_NONE; |
423 | | |
424 | 0 | return strm->internal->next.get_check(strm->internal->next.coder); |
425 | 0 | } |
426 | | |
427 | | |
428 | | extern LZMA_API(uint64_t) |
429 | | lzma_memusage(const lzma_stream *strm) |
430 | 0 | { |
431 | 0 | uint64_t memusage; |
432 | 0 | uint64_t old_memlimit; |
433 | |
|
434 | 0 | if (strm == NULL || strm->internal == NULL |
435 | 0 | || strm->internal->next.memconfig == NULL |
436 | 0 | || strm->internal->next.memconfig( |
437 | 0 | strm->internal->next.coder, |
438 | 0 | &memusage, &old_memlimit, 0) != LZMA_OK) |
439 | 0 | return 0; |
440 | | |
441 | 0 | return memusage; |
442 | 0 | } |
443 | | |
444 | | |
445 | | extern LZMA_API(uint64_t) |
446 | | lzma_memlimit_get(const lzma_stream *strm) |
447 | 0 | { |
448 | 0 | uint64_t old_memlimit; |
449 | 0 | uint64_t memusage; |
450 | |
|
451 | 0 | if (strm == NULL || strm->internal == NULL |
452 | 0 | || strm->internal->next.memconfig == NULL |
453 | 0 | || strm->internal->next.memconfig( |
454 | 0 | strm->internal->next.coder, |
455 | 0 | &memusage, &old_memlimit, 0) != LZMA_OK) |
456 | 0 | return 0; |
457 | | |
458 | 0 | return old_memlimit; |
459 | 0 | } |
460 | | |
461 | | |
462 | | extern LZMA_API(lzma_ret) |
463 | | lzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit) |
464 | 0 | { |
465 | | // Dummy variables to simplify memconfig functions |
466 | 0 | uint64_t old_memlimit; |
467 | 0 | uint64_t memusage; |
468 | |
|
469 | 0 | if (strm == NULL || strm->internal == NULL |
470 | 0 | || strm->internal->next.memconfig == NULL) |
471 | 0 | return LZMA_PROG_ERROR; |
472 | | |
473 | | // Zero is a special value that cannot be used as an actual limit. |
474 | | // If 0 was specified, use 1 instead. |
475 | 0 | if (new_memlimit == 0) |
476 | 0 | new_memlimit = 1; |
477 | |
|
478 | 0 | return strm->internal->next.memconfig(strm->internal->next.coder, |
479 | 0 | &memusage, &old_memlimit, new_memlimit); |
480 | 0 | } |