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