1228753Smm/*- 2228753Smm * Copyright (c) 2007 Kai Wang 3228753Smm * Copyright (c) 2007 Tim Kientzle 4228753Smm * All rights reserved. 5228753Smm * 6228753Smm * Redistribution and use in source and binary forms, with or without 7228753Smm * modification, are permitted provided that the following conditions 8228753Smm * are met: 9228753Smm * 1. Redistributions of source code must retain the above copyright 10228753Smm * notice, this list of conditions and the following disclaimer 11228753Smm * in this position and unchanged. 12228753Smm * 2. Redistributions in binary form must reproduce the above copyright 13228753Smm * notice, this list of conditions and the following disclaimer in the 14228753Smm * documentation and/or other materials provided with the distribution. 15228753Smm * 16228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 17228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 20228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26228753Smm */ 27228753Smm 28228753Smm#include "archive_platform.h" 29228763Smm__FBSDID("$FreeBSD: stable/10/contrib/libarchive/libarchive/archive_read_support_format_ar.c 344674 2019-02-28 22:57:09Z mm $"); 30228753Smm 31228753Smm#ifdef HAVE_SYS_STAT_H 32228753Smm#include <sys/stat.h> 33228753Smm#endif 34228753Smm#ifdef HAVE_ERRNO_H 35228753Smm#include <errno.h> 36228753Smm#endif 37228753Smm#ifdef HAVE_STDLIB_H 38228753Smm#include <stdlib.h> 39228753Smm#endif 40228753Smm#ifdef HAVE_STRING_H 41228753Smm#include <string.h> 42228753Smm#endif 43228753Smm#ifdef HAVE_LIMITS_H 44228753Smm#include <limits.h> 45228753Smm#endif 46228753Smm 47228753Smm#include "archive.h" 48228753Smm#include "archive_entry.h" 49228753Smm#include "archive_private.h" 50228753Smm#include "archive_read_private.h" 51228753Smm 52228753Smmstruct ar { 53232153Smm int64_t entry_bytes_remaining; 54232153Smm /* unconsumed is purely to track data we've gotten from readahead, 55232153Smm * but haven't yet marked as consumed. Must be paired with 56232153Smm * entry_bytes_remaining usage/modification. 57232153Smm */ 58232153Smm size_t entry_bytes_unconsumed; 59232153Smm int64_t entry_offset; 60232153Smm int64_t entry_padding; 61228753Smm char *strtab; 62228753Smm size_t strtab_size; 63232153Smm char read_global_header; 64228753Smm}; 65228753Smm 66228753Smm/* 67228753Smm * Define structure of the "ar" header. 68228753Smm */ 69228753Smm#define AR_name_offset 0 70228753Smm#define AR_name_size 16 71228753Smm#define AR_date_offset 16 72228753Smm#define AR_date_size 12 73228753Smm#define AR_uid_offset 28 74228753Smm#define AR_uid_size 6 75228753Smm#define AR_gid_offset 34 76228753Smm#define AR_gid_size 6 77228753Smm#define AR_mode_offset 40 78228753Smm#define AR_mode_size 8 79228753Smm#define AR_size_offset 48 80228753Smm#define AR_size_size 10 81228753Smm#define AR_fmag_offset 58 82228753Smm#define AR_fmag_size 2 83228753Smm 84232153Smmstatic int archive_read_format_ar_bid(struct archive_read *a, int); 85228753Smmstatic int archive_read_format_ar_cleanup(struct archive_read *a); 86228753Smmstatic int archive_read_format_ar_read_data(struct archive_read *a, 87232153Smm const void **buff, size_t *size, int64_t *offset); 88228753Smmstatic int archive_read_format_ar_skip(struct archive_read *a); 89228753Smmstatic int archive_read_format_ar_read_header(struct archive_read *a, 90228753Smm struct archive_entry *e); 91228753Smmstatic uint64_t ar_atol8(const char *p, unsigned char_cnt); 92228753Smmstatic uint64_t ar_atol10(const char *p, unsigned char_cnt); 93228753Smmstatic int ar_parse_gnu_filename_table(struct archive_read *a); 94228753Smmstatic int ar_parse_common_header(struct ar *ar, struct archive_entry *, 95228753Smm const char *h); 96228753Smm 97228753Smmint 98228753Smmarchive_read_support_format_ar(struct archive *_a) 99228753Smm{ 100228753Smm struct archive_read *a = (struct archive_read *)_a; 101228753Smm struct ar *ar; 102228753Smm int r; 103228753Smm 104232153Smm archive_check_magic(_a, ARCHIVE_READ_MAGIC, 105232153Smm ARCHIVE_STATE_NEW, "archive_read_support_format_ar"); 106232153Smm 107311042Smm ar = (struct ar *)calloc(1, sizeof(*ar)); 108228753Smm if (ar == NULL) { 109228753Smm archive_set_error(&a->archive, ENOMEM, 110228753Smm "Can't allocate ar data"); 111228753Smm return (ARCHIVE_FATAL); 112228753Smm } 113228753Smm ar->strtab = NULL; 114228753Smm 115228753Smm r = __archive_read_register_format(a, 116228753Smm ar, 117228753Smm "ar", 118228753Smm archive_read_format_ar_bid, 119228753Smm NULL, 120228753Smm archive_read_format_ar_read_header, 121228753Smm archive_read_format_ar_read_data, 122228753Smm archive_read_format_ar_skip, 123248616Smm NULL, 124302001Smm archive_read_format_ar_cleanup, 125302001Smm NULL, 126302001Smm NULL); 127228753Smm 128228753Smm if (r != ARCHIVE_OK) { 129228753Smm free(ar); 130228753Smm return (r); 131228753Smm } 132228753Smm return (ARCHIVE_OK); 133228753Smm} 134228753Smm 135228753Smmstatic int 136228753Smmarchive_read_format_ar_cleanup(struct archive_read *a) 137228753Smm{ 138228753Smm struct ar *ar; 139228753Smm 140228753Smm ar = (struct ar *)(a->format->data); 141344674Smm free(ar->strtab); 142228753Smm free(ar); 143228753Smm (a->format->data) = NULL; 144228753Smm return (ARCHIVE_OK); 145228753Smm} 146228753Smm 147228753Smmstatic int 148232153Smmarchive_read_format_ar_bid(struct archive_read *a, int best_bid) 149228753Smm{ 150228753Smm const void *h; 151228753Smm 152232153Smm (void)best_bid; /* UNUSED */ 153228753Smm 154228753Smm /* 155228753Smm * Verify the 8-byte file signature. 156228753Smm * TODO: Do we need to check more than this? 157228753Smm */ 158228753Smm if ((h = __archive_read_ahead(a, 8, NULL)) == NULL) 159228753Smm return (-1); 160232153Smm if (memcmp(h, "!<arch>\n", 8) == 0) { 161228753Smm return (64); 162228753Smm } 163228753Smm return (-1); 164228753Smm} 165228753Smm 166228753Smmstatic int 167232153Smm_ar_read_header(struct archive_read *a, struct archive_entry *entry, 168232153Smm struct ar *ar, const char *h, size_t *unconsumed) 169228753Smm{ 170228753Smm char filename[AR_name_size + 1]; 171228753Smm uint64_t number; /* Used to hold parsed numbers before validation. */ 172228753Smm size_t bsd_name_length, entry_size; 173228753Smm char *p, *st; 174228753Smm const void *b; 175228753Smm int r; 176228753Smm 177228753Smm /* Verify the magic signature on the file header. */ 178228753Smm if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) { 179228753Smm archive_set_error(&a->archive, EINVAL, 180228753Smm "Incorrect file header signature"); 181302001Smm return (ARCHIVE_FATAL); 182228753Smm } 183228753Smm 184228753Smm /* Copy filename into work buffer. */ 185228753Smm strncpy(filename, h + AR_name_offset, AR_name_size); 186228753Smm filename[AR_name_size] = '\0'; 187228753Smm 188228753Smm /* 189228753Smm * Guess the format variant based on the filename. 190228753Smm */ 191228753Smm if (a->archive.archive_format == ARCHIVE_FORMAT_AR) { 192228753Smm /* We don't already know the variant, so let's guess. */ 193228753Smm /* 194228753Smm * Biggest clue is presence of '/': GNU starts special 195228753Smm * filenames with '/', appends '/' as terminator to 196228753Smm * non-special names, so anything with '/' should be 197228753Smm * GNU except for BSD long filenames. 198228753Smm */ 199228753Smm if (strncmp(filename, "#1/", 3) == 0) 200228753Smm a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; 201228753Smm else if (strchr(filename, '/') != NULL) 202228753Smm a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU; 203228753Smm else if (strncmp(filename, "__.SYMDEF", 9) == 0) 204228753Smm a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD; 205228753Smm /* 206228753Smm * XXX Do GNU/SVR4 'ar' programs ever omit trailing '/' 207228753Smm * if name exactly fills 16-byte field? If so, we 208228753Smm * can't assume entries without '/' are BSD. XXX 209228753Smm */ 210228753Smm } 211228753Smm 212228753Smm /* Update format name from the code. */ 213228753Smm if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU) 214228753Smm a->archive.archive_format_name = "ar (GNU/SVR4)"; 215228753Smm else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD) 216228753Smm a->archive.archive_format_name = "ar (BSD)"; 217228753Smm else 218228753Smm a->archive.archive_format_name = "ar"; 219228753Smm 220228753Smm /* 221228753Smm * Remove trailing spaces from the filename. GNU and BSD 222228753Smm * variants both pad filename area out with spaces. 223228753Smm * This will only be wrong if GNU/SVR4 'ar' implementations 224228753Smm * omit trailing '/' for 16-char filenames and we have 225228753Smm * a 16-char filename that ends in ' '. 226228753Smm */ 227228753Smm p = filename + AR_name_size - 1; 228228753Smm while (p >= filename && *p == ' ') { 229228753Smm *p = '\0'; 230228753Smm p--; 231228753Smm } 232228753Smm 233228753Smm /* 234228753Smm * Remove trailing slash unless first character is '/'. 235228753Smm * (BSD entries never end in '/', so this will only trim 236228753Smm * GNU-format entries. GNU special entries start with '/' 237228753Smm * and are not terminated in '/', so we don't trim anything 238228753Smm * that starts with '/'.) 239228753Smm */ 240302001Smm if (filename[0] != '/' && p > filename && *p == '/') { 241228753Smm *p = '\0'; 242302001Smm } 243228753Smm 244302001Smm if (p < filename) { 245302001Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 246302001Smm "Found entry with empty filename"); 247302001Smm return (ARCHIVE_FATAL); 248302001Smm } 249302001Smm 250228753Smm /* 251228753Smm * '//' is the GNU filename table. 252228753Smm * Later entries can refer to names in this table. 253228753Smm */ 254228753Smm if (strcmp(filename, "//") == 0) { 255228753Smm /* This must come before any call to _read_ahead. */ 256228753Smm ar_parse_common_header(ar, entry, h); 257228753Smm archive_entry_copy_pathname(entry, filename); 258228753Smm archive_entry_set_filetype(entry, AE_IFREG); 259228753Smm /* Get the size of the filename table. */ 260228753Smm number = ar_atol10(h + AR_size_offset, AR_size_size); 261311042Smm if (number > SIZE_MAX || number > 1024 * 1024 * 1024) { 262228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 263228753Smm "Filename table too large"); 264228753Smm return (ARCHIVE_FATAL); 265228753Smm } 266228753Smm entry_size = (size_t)number; 267228753Smm if (entry_size == 0) { 268228753Smm archive_set_error(&a->archive, EINVAL, 269228753Smm "Invalid string table"); 270302001Smm return (ARCHIVE_FATAL); 271228753Smm } 272228753Smm if (ar->strtab != NULL) { 273228753Smm archive_set_error(&a->archive, EINVAL, 274228753Smm "More than one string tables exist"); 275302001Smm return (ARCHIVE_FATAL); 276228753Smm } 277228753Smm 278228753Smm /* Read the filename table into memory. */ 279228753Smm st = malloc(entry_size); 280228753Smm if (st == NULL) { 281228753Smm archive_set_error(&a->archive, ENOMEM, 282228753Smm "Can't allocate filename table buffer"); 283228753Smm return (ARCHIVE_FATAL); 284228753Smm } 285228753Smm ar->strtab = st; 286228753Smm ar->strtab_size = entry_size; 287232153Smm 288232153Smm if (*unconsumed) { 289232153Smm __archive_read_consume(a, *unconsumed); 290232153Smm *unconsumed = 0; 291232153Smm } 292232153Smm 293228753Smm if ((b = __archive_read_ahead(a, entry_size, NULL)) == NULL) 294228753Smm return (ARCHIVE_FATAL); 295228753Smm memcpy(st, b, entry_size); 296228753Smm __archive_read_consume(a, entry_size); 297228753Smm /* All contents are consumed. */ 298228753Smm ar->entry_bytes_remaining = 0; 299228753Smm archive_entry_set_size(entry, ar->entry_bytes_remaining); 300228753Smm 301228753Smm /* Parse the filename table. */ 302228753Smm return (ar_parse_gnu_filename_table(a)); 303228753Smm } 304228753Smm 305228753Smm /* 306228753Smm * GNU variant handles long filenames by storing /<number> 307228753Smm * to indicate a name stored in the filename table. 308228753Smm * XXX TODO: Verify that it's all digits... Don't be fooled 309228753Smm * by "/9xyz" XXX 310228753Smm */ 311228753Smm if (filename[0] == '/' && filename[1] >= '0' && filename[1] <= '9') { 312228753Smm number = ar_atol10(h + AR_name_offset + 1, AR_name_size - 1); 313228753Smm /* 314228753Smm * If we can't look up the real name, warn and return 315228753Smm * the entry with the wrong name. 316228753Smm */ 317311042Smm if (ar->strtab == NULL || number >= ar->strtab_size) { 318228753Smm archive_set_error(&a->archive, EINVAL, 319302001Smm "Can't find long filename for GNU/SVR4 archive entry"); 320228753Smm archive_entry_copy_pathname(entry, filename); 321228753Smm /* Parse the time, owner, mode, size fields. */ 322228753Smm ar_parse_common_header(ar, entry, h); 323302001Smm return (ARCHIVE_FATAL); 324228753Smm } 325228753Smm 326228753Smm archive_entry_copy_pathname(entry, &ar->strtab[(size_t)number]); 327228753Smm /* Parse the time, owner, mode, size fields. */ 328228753Smm return (ar_parse_common_header(ar, entry, h)); 329228753Smm } 330228753Smm 331228753Smm /* 332228753Smm * BSD handles long filenames by storing "#1/" followed by the 333228753Smm * length of filename as a decimal number, then prepends the 334228753Smm * the filename to the file contents. 335228753Smm */ 336228753Smm if (strncmp(filename, "#1/", 3) == 0) { 337228753Smm /* Parse the time, owner, mode, size fields. */ 338228753Smm /* This must occur before _read_ahead is called again. */ 339228753Smm ar_parse_common_header(ar, entry, h); 340228753Smm 341228753Smm /* Parse the size of the name, adjust the file size. */ 342228753Smm number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3); 343311042Smm /* Sanity check the filename length: 344311042Smm * = Must be <= SIZE_MAX - 1 345311042Smm * = Must be <= 1MB 346311042Smm * = Cannot be bigger than the entire entry 347311042Smm */ 348311042Smm if (number > SIZE_MAX - 1 349311042Smm || number > 1024 * 1024 350311042Smm || (int64_t)number > ar->entry_bytes_remaining) { 351228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 352228753Smm "Bad input file size"); 353228753Smm return (ARCHIVE_FATAL); 354228753Smm } 355311042Smm bsd_name_length = (size_t)number; 356228753Smm ar->entry_bytes_remaining -= bsd_name_length; 357228753Smm /* Adjust file size reported to client. */ 358228753Smm archive_entry_set_size(entry, ar->entry_bytes_remaining); 359228753Smm 360232153Smm if (*unconsumed) { 361232153Smm __archive_read_consume(a, *unconsumed); 362232153Smm *unconsumed = 0; 363232153Smm } 364232153Smm 365228753Smm /* Read the long name into memory. */ 366228753Smm if ((b = __archive_read_ahead(a, bsd_name_length, NULL)) == NULL) { 367228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 368228753Smm "Truncated input file"); 369228753Smm return (ARCHIVE_FATAL); 370228753Smm } 371228753Smm /* Store it in the entry. */ 372228753Smm p = (char *)malloc(bsd_name_length + 1); 373228753Smm if (p == NULL) { 374228753Smm archive_set_error(&a->archive, ENOMEM, 375228753Smm "Can't allocate fname buffer"); 376228753Smm return (ARCHIVE_FATAL); 377228753Smm } 378228753Smm strncpy(p, b, bsd_name_length); 379228753Smm p[bsd_name_length] = '\0'; 380232153Smm 381232153Smm __archive_read_consume(a, bsd_name_length); 382232153Smm 383228753Smm archive_entry_copy_pathname(entry, p); 384228753Smm free(p); 385228753Smm return (ARCHIVE_OK); 386228753Smm } 387228753Smm 388228753Smm /* 389228753Smm * "/" is the SVR4/GNU archive symbol table. 390344674Smm * "/SYM64/" is the SVR4/GNU 64-bit variant archive symbol table. 391228753Smm */ 392344674Smm if (strcmp(filename, "/") == 0 || strcmp(filename, "/SYM64/") == 0) { 393344674Smm archive_entry_copy_pathname(entry, filename); 394228753Smm /* Parse the time, owner, mode, size fields. */ 395228753Smm r = ar_parse_common_header(ar, entry, h); 396228753Smm /* Force the file type to a regular file. */ 397228753Smm archive_entry_set_filetype(entry, AE_IFREG); 398228753Smm return (r); 399228753Smm } 400228753Smm 401228753Smm /* 402228753Smm * "__.SYMDEF" is a BSD archive symbol table. 403228753Smm */ 404228753Smm if (strcmp(filename, "__.SYMDEF") == 0) { 405228753Smm archive_entry_copy_pathname(entry, filename); 406228753Smm /* Parse the time, owner, mode, size fields. */ 407228753Smm return (ar_parse_common_header(ar, entry, h)); 408228753Smm } 409228753Smm 410228753Smm /* 411228753Smm * Otherwise, this is a standard entry. The filename 412228753Smm * has already been trimmed as much as possible, based 413228753Smm * on our current knowledge of the format. 414228753Smm */ 415228753Smm archive_entry_copy_pathname(entry, filename); 416228753Smm return (ar_parse_common_header(ar, entry, h)); 417228753Smm} 418228753Smm 419228753Smmstatic int 420232153Smmarchive_read_format_ar_read_header(struct archive_read *a, 421232153Smm struct archive_entry *entry) 422232153Smm{ 423232153Smm struct ar *ar = (struct ar*)(a->format->data); 424232153Smm size_t unconsumed; 425232153Smm const void *header_data; 426232153Smm int ret; 427232153Smm 428232153Smm if (!ar->read_global_header) { 429232153Smm /* 430232153Smm * We are now at the beginning of the archive, 431232153Smm * so we need first consume the ar global header. 432232153Smm */ 433232153Smm __archive_read_consume(a, 8); 434232153Smm ar->read_global_header = 1; 435232153Smm /* Set a default format code for now. */ 436232153Smm a->archive.archive_format = ARCHIVE_FORMAT_AR; 437232153Smm } 438232153Smm 439232153Smm /* Read the header for the next file entry. */ 440232153Smm if ((header_data = __archive_read_ahead(a, 60, NULL)) == NULL) 441232153Smm /* Broken header. */ 442232153Smm return (ARCHIVE_EOF); 443232153Smm 444232153Smm unconsumed = 60; 445232153Smm 446232153Smm ret = _ar_read_header(a, entry, ar, (const char *)header_data, &unconsumed); 447232153Smm 448232153Smm if (unconsumed) 449232153Smm __archive_read_consume(a, unconsumed); 450232153Smm 451232153Smm return ret; 452232153Smm} 453232153Smm 454232153Smm 455232153Smmstatic int 456228753Smmar_parse_common_header(struct ar *ar, struct archive_entry *entry, 457228753Smm const char *h) 458228753Smm{ 459228753Smm uint64_t n; 460228753Smm 461228753Smm /* Copy remaining header */ 462339006Smm archive_entry_set_filetype(entry, AE_IFREG); 463228753Smm archive_entry_set_mtime(entry, 464228753Smm (time_t)ar_atol10(h + AR_date_offset, AR_date_size), 0L); 465228753Smm archive_entry_set_uid(entry, 466228753Smm (uid_t)ar_atol10(h + AR_uid_offset, AR_uid_size)); 467228753Smm archive_entry_set_gid(entry, 468228753Smm (gid_t)ar_atol10(h + AR_gid_offset, AR_gid_size)); 469228753Smm archive_entry_set_mode(entry, 470228753Smm (mode_t)ar_atol8(h + AR_mode_offset, AR_mode_size)); 471228753Smm n = ar_atol10(h + AR_size_offset, AR_size_size); 472228753Smm 473228753Smm ar->entry_offset = 0; 474228753Smm ar->entry_padding = n % 2; 475228753Smm archive_entry_set_size(entry, n); 476228753Smm ar->entry_bytes_remaining = n; 477228753Smm return (ARCHIVE_OK); 478228753Smm} 479228753Smm 480228753Smmstatic int 481228753Smmarchive_read_format_ar_read_data(struct archive_read *a, 482232153Smm const void **buff, size_t *size, int64_t *offset) 483228753Smm{ 484228753Smm ssize_t bytes_read; 485228753Smm struct ar *ar; 486228753Smm 487228753Smm ar = (struct ar *)(a->format->data); 488228753Smm 489232153Smm if (ar->entry_bytes_unconsumed) { 490232153Smm __archive_read_consume(a, ar->entry_bytes_unconsumed); 491232153Smm ar->entry_bytes_unconsumed = 0; 492232153Smm } 493232153Smm 494228753Smm if (ar->entry_bytes_remaining > 0) { 495228753Smm *buff = __archive_read_ahead(a, 1, &bytes_read); 496228753Smm if (bytes_read == 0) { 497228753Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 498228753Smm "Truncated ar archive"); 499228753Smm return (ARCHIVE_FATAL); 500228753Smm } 501228753Smm if (bytes_read < 0) 502228753Smm return (ARCHIVE_FATAL); 503228753Smm if (bytes_read > ar->entry_bytes_remaining) 504228753Smm bytes_read = (ssize_t)ar->entry_bytes_remaining; 505228753Smm *size = bytes_read; 506232153Smm ar->entry_bytes_unconsumed = bytes_read; 507228753Smm *offset = ar->entry_offset; 508228753Smm ar->entry_offset += bytes_read; 509228753Smm ar->entry_bytes_remaining -= bytes_read; 510228753Smm return (ARCHIVE_OK); 511228753Smm } else { 512232153Smm int64_t skipped = __archive_read_consume(a, ar->entry_padding); 513232153Smm if (skipped >= 0) { 514232153Smm ar->entry_padding -= skipped; 515228753Smm } 516232153Smm if (ar->entry_padding) { 517232153Smm if (skipped >= 0) { 518232153Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 519232153Smm "Truncated ar archive- failed consuming padding"); 520232153Smm } 521232153Smm return (ARCHIVE_FATAL); 522232153Smm } 523228753Smm *buff = NULL; 524228753Smm *size = 0; 525228753Smm *offset = ar->entry_offset; 526228753Smm return (ARCHIVE_EOF); 527228753Smm } 528228753Smm} 529228753Smm 530228753Smmstatic int 531228753Smmarchive_read_format_ar_skip(struct archive_read *a) 532228753Smm{ 533232153Smm int64_t bytes_skipped; 534228753Smm struct ar* ar; 535228753Smm 536228753Smm ar = (struct ar *)(a->format->data); 537228753Smm 538232153Smm bytes_skipped = __archive_read_consume(a, 539232153Smm ar->entry_bytes_remaining + ar->entry_padding 540232153Smm + ar->entry_bytes_unconsumed); 541228753Smm if (bytes_skipped < 0) 542228753Smm return (ARCHIVE_FATAL); 543228753Smm 544228753Smm ar->entry_bytes_remaining = 0; 545232153Smm ar->entry_bytes_unconsumed = 0; 546228753Smm ar->entry_padding = 0; 547228753Smm 548228753Smm return (ARCHIVE_OK); 549228753Smm} 550228753Smm 551228753Smmstatic int 552228753Smmar_parse_gnu_filename_table(struct archive_read *a) 553228753Smm{ 554228753Smm struct ar *ar; 555228753Smm char *p; 556228753Smm size_t size; 557228753Smm 558228753Smm ar = (struct ar*)(a->format->data); 559228753Smm size = ar->strtab_size; 560228753Smm 561228753Smm for (p = ar->strtab; p < ar->strtab + size - 1; ++p) { 562228753Smm if (*p == '/') { 563228753Smm *p++ = '\0'; 564228753Smm if (*p != '\n') 565228753Smm goto bad_string_table; 566228753Smm *p = '\0'; 567228753Smm } 568228753Smm } 569228753Smm /* 570228753Smm * GNU ar always pads the table to an even size. 571228753Smm * The pad character is either '\n' or '`'. 572228753Smm */ 573228753Smm if (p != ar->strtab + size && *p != '\n' && *p != '`') 574228753Smm goto bad_string_table; 575228753Smm 576228753Smm /* Enforce zero termination. */ 577228753Smm ar->strtab[size - 1] = '\0'; 578228753Smm 579228753Smm return (ARCHIVE_OK); 580228753Smm 581228753Smmbad_string_table: 582228753Smm archive_set_error(&a->archive, EINVAL, 583228753Smm "Invalid string table"); 584228753Smm free(ar->strtab); 585228753Smm ar->strtab = NULL; 586302001Smm return (ARCHIVE_FATAL); 587228753Smm} 588228753Smm 589228753Smmstatic uint64_t 590228753Smmar_atol8(const char *p, unsigned char_cnt) 591228753Smm{ 592228753Smm uint64_t l, limit, last_digit_limit; 593228753Smm unsigned int digit, base; 594228753Smm 595228753Smm base = 8; 596228753Smm limit = UINT64_MAX / base; 597228753Smm last_digit_limit = UINT64_MAX % base; 598228753Smm 599228753Smm while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) 600228753Smm p++; 601228753Smm 602228753Smm l = 0; 603228753Smm digit = *p - '0'; 604228753Smm while (*p >= '0' && digit < base && char_cnt-- > 0) { 605228753Smm if (l>limit || (l == limit && digit > last_digit_limit)) { 606228753Smm l = UINT64_MAX; /* Truncate on overflow. */ 607228753Smm break; 608228753Smm } 609228753Smm l = (l * base) + digit; 610228753Smm digit = *++p - '0'; 611228753Smm } 612228753Smm return (l); 613228753Smm} 614228753Smm 615228753Smmstatic uint64_t 616228753Smmar_atol10(const char *p, unsigned char_cnt) 617228753Smm{ 618228753Smm uint64_t l, limit, last_digit_limit; 619228753Smm unsigned int base, digit; 620228753Smm 621228753Smm base = 10; 622228753Smm limit = UINT64_MAX / base; 623228753Smm last_digit_limit = UINT64_MAX % base; 624228753Smm 625228753Smm while ((*p == ' ' || *p == '\t') && char_cnt-- > 0) 626228753Smm p++; 627228753Smm l = 0; 628228753Smm digit = *p - '0'; 629228753Smm while (*p >= '0' && digit < base && char_cnt-- > 0) { 630228753Smm if (l > limit || (l == limit && digit > last_digit_limit)) { 631228753Smm l = UINT64_MAX; /* Truncate on overflow. */ 632228753Smm break; 633228753Smm } 634228753Smm l = (l * base) + digit; 635228753Smm digit = *++p - '0'; 636228753Smm } 637228753Smm return (l); 638228753Smm} 639