archive_read_support_format_ar.c revision 311042
1238825Smm/*-
2238825Smm * Copyright (c) 2007 Kai Wang
3238825Smm * Copyright (c) 2007 Tim Kientzle
4238825Smm * All rights reserved.
5238825Smm *
6238825Smm * Redistribution and use in source and binary forms, with or without
7238825Smm * modification, are permitted provided that the following conditions
8238825Smm * are met:
9238825Smm * 1. Redistributions of source code must retain the above copyright
10238825Smm *    notice, this list of conditions and the following disclaimer
11238825Smm *    in this position and unchanged.
12238825Smm * 2. Redistributions in binary form must reproduce the above copyright
13238825Smm *    notice, this list of conditions and the following disclaimer in the
14238825Smm *    documentation and/or other materials provided with the distribution.
15238825Smm *
16238825Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17238825Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18238825Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19238825Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20238825Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21238825Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22238825Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23238825Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24238825Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25238825Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26238825Smm */
27238825Smm
28238825Smm#include "archive_platform.h"
29238825Smm__FBSDID("$FreeBSD: stable/10/contrib/libarchive/libarchive/archive_read_support_format_ar.c 311042 2017-01-02 01:43:11Z mm $");
30238825Smm
31238825Smm#ifdef HAVE_SYS_STAT_H
32238825Smm#include <sys/stat.h>
33238825Smm#endif
34238825Smm#ifdef HAVE_ERRNO_H
35238825Smm#include <errno.h>
36238825Smm#endif
37238825Smm#ifdef HAVE_STDLIB_H
38238825Smm#include <stdlib.h>
39238825Smm#endif
40238825Smm#ifdef HAVE_STRING_H
41238825Smm#include <string.h>
42238825Smm#endif
43302001Smm#ifdef HAVE_LIMITS_H
44238825Smm#include <limits.h>
45238825Smm#endif
46238825Smm
47238825Smm#include "archive.h"
48238825Smm#include "archive_entry.h"
49238825Smm#include "archive_private.h"
50238825Smm#include "archive_read_private.h"
51238825Smm
52238825Smmstruct ar {
53238825Smm	int64_t	 entry_bytes_remaining;
54238825Smm	/* unconsumed is purely to track data we've gotten from readahead,
55238825Smm	 * but haven't yet marked as consumed.  Must be paired with
56238825Smm	 * entry_bytes_remaining usage/modification.
57238825Smm	 */
58238825Smm	size_t   entry_bytes_unconsumed;
59238825Smm	int64_t	 entry_offset;
60238825Smm	int64_t	 entry_padding;
61238825Smm	char	*strtab;
62238825Smm	size_t	 strtab_size;
63238825Smm	char	 read_global_header;
64238825Smm};
65238825Smm
66238825Smm/*
67238825Smm * Define structure of the "ar" header.
68238825Smm */
69238825Smm#define AR_name_offset 0
70238825Smm#define AR_name_size 16
71238825Smm#define AR_date_offset 16
72238825Smm#define AR_date_size 12
73238825Smm#define AR_uid_offset 28
74238825Smm#define AR_uid_size 6
75238825Smm#define AR_gid_offset 34
76238825Smm#define AR_gid_size 6
77238825Smm#define AR_mode_offset 40
78238825Smm#define AR_mode_size 8
79238825Smm#define AR_size_offset 48
80238825Smm#define AR_size_size 10
81238825Smm#define AR_fmag_offset 58
82238825Smm#define AR_fmag_size 2
83238825Smm
84238825Smmstatic int	archive_read_format_ar_bid(struct archive_read *a, int);
85238825Smmstatic int	archive_read_format_ar_cleanup(struct archive_read *a);
86238825Smmstatic int	archive_read_format_ar_read_data(struct archive_read *a,
87238825Smm		    const void **buff, size_t *size, int64_t *offset);
88238825Smmstatic int	archive_read_format_ar_skip(struct archive_read *a);
89238825Smmstatic int	archive_read_format_ar_read_header(struct archive_read *a,
90238825Smm		    struct archive_entry *e);
91238825Smmstatic uint64_t	ar_atol8(const char *p, unsigned char_cnt);
92238825Smmstatic uint64_t	ar_atol10(const char *p, unsigned char_cnt);
93238825Smmstatic int	ar_parse_gnu_filename_table(struct archive_read *a);
94238825Smmstatic int	ar_parse_common_header(struct ar *ar, struct archive_entry *,
95238825Smm		    const char *h);
96348608Smm
97348608Smmint
98348608Smmarchive_read_support_format_ar(struct archive *_a)
99238825Smm{
100238825Smm	struct archive_read *a = (struct archive_read *)_a;
101238825Smm	struct ar *ar;
102238825Smm	int r;
103238825Smm
104238825Smm	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
105238825Smm	    ARCHIVE_STATE_NEW, "archive_read_support_format_ar");
106238825Smm
107238825Smm	ar = (struct ar *)calloc(1, sizeof(*ar));
108238825Smm	if (ar == NULL) {
109238825Smm		archive_set_error(&a->archive, ENOMEM,
110238825Smm		    "Can't allocate ar data");
111238825Smm		return (ARCHIVE_FATAL);
112238825Smm	}
113238825Smm	ar->strtab = NULL;
114238825Smm
115238825Smm	r = __archive_read_register_format(a,
116238825Smm	    ar,
117238825Smm	    "ar",
118238825Smm	    archive_read_format_ar_bid,
119238825Smm	    NULL,
120238825Smm	    archive_read_format_ar_read_header,
121238825Smm	    archive_read_format_ar_read_data,
122238825Smm	    archive_read_format_ar_skip,
123238825Smm	    NULL,
124238825Smm	    archive_read_format_ar_cleanup,
125238825Smm	    NULL,
126238825Smm	    NULL);
127238825Smm
128238825Smm	if (r != ARCHIVE_OK) {
129238825Smm		free(ar);
130238825Smm		return (r);
131238825Smm	}
132238825Smm	return (ARCHIVE_OK);
133238825Smm}
134238825Smm
135238825Smmstatic int
136238825Smmarchive_read_format_ar_cleanup(struct archive_read *a)
137238825Smm{
138238825Smm	struct ar *ar;
139238825Smm
140238825Smm	ar = (struct ar *)(a->format->data);
141238825Smm	if (ar->strtab)
142238825Smm		free(ar->strtab);
143238825Smm	free(ar);
144238825Smm	(a->format->data) = NULL;
145238825Smm	return (ARCHIVE_OK);
146238825Smm}
147238825Smm
148238825Smmstatic int
149238825Smmarchive_read_format_ar_bid(struct archive_read *a, int best_bid)
150238825Smm{
151238825Smm	const void *h;
152238825Smm
153238825Smm	(void)best_bid; /* UNUSED */
154238825Smm
155238825Smm	/*
156238825Smm	 * Verify the 8-byte file signature.
157238825Smm	 * TODO: Do we need to check more than this?
158238825Smm	 */
159238825Smm	if ((h = __archive_read_ahead(a, 8, NULL)) == NULL)
160238825Smm		return (-1);
161238825Smm	if (memcmp(h, "!<arch>\n", 8) == 0) {
162238825Smm		return (64);
163238825Smm	}
164238825Smm	return (-1);
165238825Smm}
166238825Smm
167238825Smmstatic int
168238825Smm_ar_read_header(struct archive_read *a, struct archive_entry *entry,
169238825Smm	struct ar *ar, const char *h, size_t *unconsumed)
170238825Smm{
171238825Smm	char filename[AR_name_size + 1];
172238825Smm	uint64_t number; /* Used to hold parsed numbers before validation. */
173238825Smm	size_t bsd_name_length, entry_size;
174238825Smm	char *p, *st;
175238825Smm	const void *b;
176238825Smm	int r;
177238825Smm
178238825Smm	/* Verify the magic signature on the file header. */
179238825Smm	if (strncmp(h + AR_fmag_offset, "`\n", 2) != 0) {
180238825Smm		archive_set_error(&a->archive, EINVAL,
181238825Smm		    "Incorrect file header signature");
182238825Smm		return (ARCHIVE_FATAL);
183238825Smm	}
184238825Smm
185238825Smm	/* Copy filename into work buffer. */
186238825Smm	strncpy(filename, h + AR_name_offset, AR_name_size);
187238825Smm	filename[AR_name_size] = '\0';
188238825Smm
189238825Smm	/*
190238825Smm	 * Guess the format variant based on the filename.
191238825Smm	 */
192238825Smm	if (a->archive.archive_format == ARCHIVE_FORMAT_AR) {
193238825Smm		/* We don't already know the variant, so let's guess. */
194238825Smm		/*
195238825Smm		 * Biggest clue is presence of '/': GNU starts special
196238825Smm		 * filenames with '/', appends '/' as terminator to
197238825Smm		 * non-special names, so anything with '/' should be
198238825Smm		 * GNU except for BSD long filenames.
199238825Smm		 */
200238825Smm		if (strncmp(filename, "#1/", 3) == 0)
201238825Smm			a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD;
202238825Smm		else if (strchr(filename, '/') != NULL)
203238825Smm			a->archive.archive_format = ARCHIVE_FORMAT_AR_GNU;
204238825Smm		else if (strncmp(filename, "__.SYMDEF", 9) == 0)
205238825Smm			a->archive.archive_format = ARCHIVE_FORMAT_AR_BSD;
206238825Smm		/*
207238825Smm		 * XXX Do GNU/SVR4 'ar' programs ever omit trailing '/'
208238825Smm		 * if name exactly fills 16-byte field?  If so, we
209238825Smm		 * can't assume entries without '/' are BSD. XXX
210238825Smm		 */
211238825Smm	}
212238825Smm
213238825Smm	/* Update format name from the code. */
214238825Smm	if (a->archive.archive_format == ARCHIVE_FORMAT_AR_GNU)
215238825Smm		a->archive.archive_format_name = "ar (GNU/SVR4)";
216238825Smm	else if (a->archive.archive_format == ARCHIVE_FORMAT_AR_BSD)
217238825Smm		a->archive.archive_format_name = "ar (BSD)";
218238825Smm	else
219238825Smm		a->archive.archive_format_name = "ar";
220238825Smm
221238825Smm	/*
222238825Smm	 * Remove trailing spaces from the filename.  GNU and BSD
223238825Smm	 * variants both pad filename area out with spaces.
224238825Smm	 * This will only be wrong if GNU/SVR4 'ar' implementations
225238825Smm	 * omit trailing '/' for 16-char filenames and we have
226238825Smm	 * a 16-char filename that ends in ' '.
227238825Smm	 */
228238825Smm	p = filename + AR_name_size - 1;
229348608Smm	while (p >= filename && *p == ' ') {
230238825Smm		*p = '\0';
231238825Smm		p--;
232238825Smm	}
233238825Smm
234238825Smm	/*
235238825Smm	 * Remove trailing slash unless first character is '/'.
236238825Smm	 * (BSD entries never end in '/', so this will only trim
237238825Smm	 * GNU-format entries.  GNU special entries start with '/'
238238825Smm	 * and are not terminated in '/', so we don't trim anything
239238825Smm	 * that starts with '/'.)
240238825Smm	 */
241238825Smm	if (filename[0] != '/' && p > filename && *p == '/') {
242238825Smm		*p = '\0';
243238825Smm	}
244238825Smm
245238825Smm	if (p < filename) {
246238825Smm		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
247238825Smm		    "Found entry with empty filename");
248238825Smm		return (ARCHIVE_FATAL);
249238825Smm	}
250238825Smm
251238825Smm	/*
252238825Smm	 * '//' is the GNU filename table.
253238825Smm	 * Later entries can refer to names in this table.
254238825Smm	 */
255238825Smm	if (strcmp(filename, "//") == 0) {
256238825Smm		/* This must come before any call to _read_ahead. */
257238825Smm		ar_parse_common_header(ar, entry, h);
258238825Smm		archive_entry_copy_pathname(entry, filename);
259238825Smm		archive_entry_set_filetype(entry, AE_IFREG);
260238825Smm		/* Get the size of the filename table. */
261238825Smm		number = ar_atol10(h + AR_size_offset, AR_size_size);
262238825Smm		if (number > SIZE_MAX || number > 1024 * 1024 * 1024) {
263238825Smm			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
264238825Smm			    "Filename table too large");
265238825Smm			return (ARCHIVE_FATAL);
266238825Smm		}
267238825Smm		entry_size = (size_t)number;
268238825Smm		if (entry_size == 0) {
269238825Smm			archive_set_error(&a->archive, EINVAL,
270238825Smm			    "Invalid string table");
271238825Smm			return (ARCHIVE_FATAL);
272238825Smm		}
273238825Smm		if (ar->strtab != NULL) {
274238825Smm			archive_set_error(&a->archive, EINVAL,
275238825Smm			    "More than one string tables exist");
276238825Smm			return (ARCHIVE_FATAL);
277238825Smm		}
278238825Smm
279238825Smm		/* Read the filename table into memory. */
280238825Smm		st = malloc(entry_size);
281238825Smm		if (st == NULL) {
282238825Smm			archive_set_error(&a->archive, ENOMEM,
283238825Smm			    "Can't allocate filename table buffer");
284238825Smm			return (ARCHIVE_FATAL);
285238825Smm		}
286238825Smm		ar->strtab = st;
287238825Smm		ar->strtab_size = entry_size;
288238825Smm
289238825Smm		if (*unconsumed) {
290238825Smm			__archive_read_consume(a, *unconsumed);
291238825Smm			*unconsumed = 0;
292238825Smm		}
293238825Smm
294238825Smm		if ((b = __archive_read_ahead(a, entry_size, NULL)) == NULL)
295238825Smm			return (ARCHIVE_FATAL);
296238825Smm		memcpy(st, b, entry_size);
297238825Smm		__archive_read_consume(a, entry_size);
298238825Smm		/* All contents are consumed. */
299238825Smm		ar->entry_bytes_remaining = 0;
300238825Smm		archive_entry_set_size(entry, ar->entry_bytes_remaining);
301238825Smm
302238825Smm		/* Parse the filename table. */
303238825Smm		return (ar_parse_gnu_filename_table(a));
304238825Smm	}
305238825Smm
306238825Smm	/*
307238825Smm	 * GNU variant handles long filenames by storing /<number>
308238825Smm	 * to indicate a name stored in the filename table.
309238825Smm	 * XXX TODO: Verify that it's all digits... Don't be fooled
310238825Smm	 * by "/9xyz" XXX
311238825Smm	 */
312238825Smm	if (filename[0] == '/' && filename[1] >= '0' && filename[1] <= '9') {
313238825Smm		number = ar_atol10(h + AR_name_offset + 1, AR_name_size - 1);
314238825Smm		/*
315238825Smm		 * If we can't look up the real name, warn and return
316238825Smm		 * the entry with the wrong name.
317238825Smm		 */
318238825Smm		if (ar->strtab == NULL || number >= ar->strtab_size) {
319238825Smm			archive_set_error(&a->archive, EINVAL,
320238825Smm			    "Can't find long filename for GNU/SVR4 archive entry");
321238825Smm			archive_entry_copy_pathname(entry, filename);
322238825Smm			/* Parse the time, owner, mode, size fields. */
323238825Smm			ar_parse_common_header(ar, entry, h);
324238825Smm			return (ARCHIVE_FATAL);
325238825Smm		}
326238825Smm
327238825Smm		archive_entry_copy_pathname(entry, &ar->strtab[(size_t)number]);
328238825Smm		/* Parse the time, owner, mode, size fields. */
329238825Smm		return (ar_parse_common_header(ar, entry, h));
330238825Smm	}
331238825Smm
332238825Smm	/*
333238825Smm	 * BSD handles long filenames by storing "#1/" followed by the
334238825Smm	 * length of filename as a decimal number, then prepends the
335238825Smm	 * the filename to the file contents.
336238825Smm	 */
337238825Smm	if (strncmp(filename, "#1/", 3) == 0) {
338238825Smm		/* Parse the time, owner, mode, size fields. */
339238825Smm		/* This must occur before _read_ahead is called again. */
340238825Smm		ar_parse_common_header(ar, entry, h);
341238825Smm
342238825Smm		/* Parse the size of the name, adjust the file size. */
343238825Smm		number = ar_atol10(h + AR_name_offset + 3, AR_name_size - 3);
344238825Smm		/* Sanity check the filename length:
345238825Smm		 *   = Must be <= SIZE_MAX - 1
346238825Smm		 *   = Must be <= 1MB
347238825Smm		 *   = Cannot be bigger than the entire entry
348238825Smm		 */
349238825Smm		if (number > SIZE_MAX - 1
350238825Smm		    || number > 1024 * 1024
351238825Smm		    || (int64_t)number > ar->entry_bytes_remaining) {
352238825Smm			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
353238825Smm			    "Bad input file size");
354238825Smm			return (ARCHIVE_FATAL);
355238825Smm		}
356238825Smm		bsd_name_length = (size_t)number;
357238825Smm		ar->entry_bytes_remaining -= bsd_name_length;
358238825Smm		/* Adjust file size reported to client. */
359238825Smm		archive_entry_set_size(entry, ar->entry_bytes_remaining);
360238825Smm
361238825Smm		if (*unconsumed) {
362238825Smm			__archive_read_consume(a, *unconsumed);
363238825Smm			*unconsumed = 0;
364238825Smm		}
365238825Smm
366238825Smm		/* Read the long name into memory. */
367238825Smm		if ((b = __archive_read_ahead(a, bsd_name_length, NULL)) == NULL) {
368238825Smm			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
369238825Smm			    "Truncated input file");
370238825Smm			return (ARCHIVE_FATAL);
371238825Smm		}
372238825Smm		/* Store it in the entry. */
373238825Smm		p = (char *)malloc(bsd_name_length + 1);
374238825Smm		if (p == NULL) {
375238825Smm			archive_set_error(&a->archive, ENOMEM,
376238825Smm			    "Can't allocate fname buffer");
377238825Smm			return (ARCHIVE_FATAL);
378238825Smm		}
379238825Smm		strncpy(p, b, bsd_name_length);
380238825Smm		p[bsd_name_length] = '\0';
381238825Smm
382238825Smm		__archive_read_consume(a, bsd_name_length);
383238825Smm
384238825Smm		archive_entry_copy_pathname(entry, p);
385238825Smm		free(p);
386238825Smm		return (ARCHIVE_OK);
387238825Smm	}
388238825Smm
389238825Smm	/*
390238825Smm	 * "/" is the SVR4/GNU archive symbol table.
391238825Smm	 */
392238825Smm	if (strcmp(filename, "/") == 0) {
393238825Smm		archive_entry_copy_pathname(entry, "/");
394238825Smm		/* Parse the time, owner, mode, size fields. */
395238825Smm		r = ar_parse_common_header(ar, entry, h);
396238825Smm		/* Force the file type to a regular file. */
397238825Smm		archive_entry_set_filetype(entry, AE_IFREG);
398238825Smm		return (r);
399238825Smm	}
400238825Smm
401238825Smm	/*
402238825Smm	 * "__.SYMDEF" is a BSD archive symbol table.
403238825Smm	 */
404238825Smm	if (strcmp(filename, "__.SYMDEF") == 0) {
405238825Smm		archive_entry_copy_pathname(entry, filename);
406238825Smm		/* Parse the time, owner, mode, size fields. */
407238825Smm		return (ar_parse_common_header(ar, entry, h));
408238825Smm	}
409238825Smm
410238825Smm	/*
411238825Smm	 * Otherwise, this is a standard entry.  The filename
412238825Smm	 * has already been trimmed as much as possible, based
413238825Smm	 * on our current knowledge of the format.
414238825Smm	 */
415238825Smm	archive_entry_copy_pathname(entry, filename);
416238825Smm	return (ar_parse_common_header(ar, entry, h));
417238825Smm}
418238825Smm
419238825Smmstatic int
420238825Smmarchive_read_format_ar_read_header(struct archive_read *a,
421238825Smm    struct archive_entry *entry)
422238825Smm{
423238825Smm	struct ar *ar = (struct ar*)(a->format->data);
424238825Smm	size_t unconsumed;
425238825Smm	const void *header_data;
426238825Smm	int ret;
427238825Smm
428238825Smm	if (!ar->read_global_header) {
429238825Smm		/*
430238825Smm		 * We are now at the beginning of the archive,
431238825Smm		 * so we need first consume the ar global header.
432238825Smm		 */
433238825Smm		__archive_read_consume(a, 8);
434238825Smm		ar->read_global_header = 1;
435238825Smm		/* Set a default format code for now. */
436238825Smm		a->archive.archive_format = ARCHIVE_FORMAT_AR;
437238825Smm	}
438238825Smm
439238825Smm	/* Read the header for the next file entry. */
440238825Smm	if ((header_data = __archive_read_ahead(a, 60, NULL)) == NULL)
441238825Smm		/* Broken header. */
442238825Smm		return (ARCHIVE_EOF);
443238825Smm
444238825Smm	unconsumed = 60;
445238825Smm
446238825Smm	ret = _ar_read_header(a, entry, ar, (const char *)header_data, &unconsumed);
447238825Smm
448238825Smm	if (unconsumed)
449238825Smm		__archive_read_consume(a, unconsumed);
450238825Smm
451238825Smm	return ret;
452238825Smm}
453238825Smm
454238825Smm
455238825Smmstatic int
456238825Smmar_parse_common_header(struct ar *ar, struct archive_entry *entry,
457238825Smm    const char *h)
458238825Smm{
459238825Smm	uint64_t n;
460238825Smm
461238825Smm	/* Copy remaining header */
462238825Smm	archive_entry_set_mtime(entry,
463238825Smm	    (time_t)ar_atol10(h + AR_date_offset, AR_date_size), 0L);
464238825Smm	archive_entry_set_uid(entry,
465238825Smm	    (uid_t)ar_atol10(h + AR_uid_offset, AR_uid_size));
466238825Smm	archive_entry_set_gid(entry,
467238825Smm	    (gid_t)ar_atol10(h + AR_gid_offset, AR_gid_size));
468238825Smm	archive_entry_set_mode(entry,
469238825Smm	    (mode_t)ar_atol8(h + AR_mode_offset, AR_mode_size));
470238825Smm	n = ar_atol10(h + AR_size_offset, AR_size_size);
471238825Smm
472238825Smm	ar->entry_offset = 0;
473238825Smm	ar->entry_padding = n % 2;
474238825Smm	archive_entry_set_size(entry, n);
475238825Smm	ar->entry_bytes_remaining = n;
476238825Smm	return (ARCHIVE_OK);
477238825Smm}
478348608Smm
479348608Smmstatic int
480348608Smmarchive_read_format_ar_read_data(struct archive_read *a,
481348608Smm    const void **buff, size_t *size, int64_t *offset)
482348608Smm{
483348608Smm	ssize_t bytes_read;
484348608Smm	struct ar *ar;
485348608Smm
486348608Smm	ar = (struct ar *)(a->format->data);
487348608Smm
488348608Smm	if (ar->entry_bytes_unconsumed) {
489348608Smm		__archive_read_consume(a, ar->entry_bytes_unconsumed);
490348608Smm		ar->entry_bytes_unconsumed = 0;
491348608Smm	}
492348608Smm
493348608Smm	if (ar->entry_bytes_remaining > 0) {
494348608Smm		*buff = __archive_read_ahead(a, 1, &bytes_read);
495348608Smm		if (bytes_read == 0) {
496348608Smm			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
497348608Smm			    "Truncated ar archive");
498348608Smm			return (ARCHIVE_FATAL);
499348608Smm		}
500313571Smm		if (bytes_read < 0)
501238825Smm			return (ARCHIVE_FATAL);
502238825Smm		if (bytes_read > ar->entry_bytes_remaining)
503238825Smm			bytes_read = (ssize_t)ar->entry_bytes_remaining;
504238825Smm		*size = bytes_read;
505238825Smm		ar->entry_bytes_unconsumed = bytes_read;
506238825Smm		*offset = ar->entry_offset;
507238825Smm		ar->entry_offset += bytes_read;
508238825Smm		ar->entry_bytes_remaining -= bytes_read;
509238825Smm		return (ARCHIVE_OK);
510238825Smm	} else {
511238825Smm		int64_t skipped = __archive_read_consume(a, ar->entry_padding);
512238825Smm		if (skipped >= 0) {
513238825Smm			ar->entry_padding -= skipped;
514238825Smm		}
515238825Smm		if (ar->entry_padding) {
516238825Smm			if (skipped >= 0) {
517238825Smm				archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
518238825Smm					"Truncated ar archive- failed consuming padding");
519238825Smm			}
520238825Smm			return (ARCHIVE_FATAL);
521238825Smm		}
522238825Smm		*buff = NULL;
523238825Smm		*size = 0;
524238825Smm		*offset = ar->entry_offset;
525238825Smm		return (ARCHIVE_EOF);
526238825Smm	}
527238825Smm}
528238825Smm
529238825Smmstatic int
530238825Smmarchive_read_format_ar_skip(struct archive_read *a)
531238825Smm{
532238825Smm	int64_t bytes_skipped;
533238825Smm	struct ar* ar;
534238825Smm
535238825Smm	ar = (struct ar *)(a->format->data);
536238825Smm
537238825Smm	bytes_skipped = __archive_read_consume(a,
538238825Smm	    ar->entry_bytes_remaining + ar->entry_padding
539238825Smm	    + ar->entry_bytes_unconsumed);
540238825Smm	if (bytes_skipped < 0)
541238825Smm		return (ARCHIVE_FATAL);
542238825Smm
543238825Smm	ar->entry_bytes_remaining = 0;
544238825Smm	ar->entry_bytes_unconsumed = 0;
545238825Smm	ar->entry_padding = 0;
546238825Smm
547238825Smm	return (ARCHIVE_OK);
548238825Smm}
549238825Smm
550238825Smmstatic int
551238825Smmar_parse_gnu_filename_table(struct archive_read *a)
552238825Smm{
553238825Smm	struct ar *ar;
554238825Smm	char *p;
555238825Smm	size_t size;
556238825Smm
557238825Smm	ar = (struct ar*)(a->format->data);
558238825Smm	size = ar->strtab_size;
559238825Smm
560238825Smm	for (p = ar->strtab; p < ar->strtab + size - 1; ++p) {
561238825Smm		if (*p == '/') {
562238825Smm			*p++ = '\0';
563238825Smm			if (*p != '\n')
564238825Smm				goto bad_string_table;
565238825Smm			*p = '\0';
566238825Smm		}
567238825Smm	}
568238825Smm	/*
569238825Smm	 * GNU ar always pads the table to an even size.
570238825Smm	 * The pad character is either '\n' or '`'.
571238825Smm	 */
572238825Smm	if (p != ar->strtab + size && *p != '\n' && *p != '`')
573238825Smm		goto bad_string_table;
574238825Smm
575238825Smm	/* Enforce zero termination. */
576238825Smm	ar->strtab[size - 1] = '\0';
577238825Smm
578238825Smm	return (ARCHIVE_OK);
579238825Smm
580238825Smmbad_string_table:
581238825Smm	archive_set_error(&a->archive, EINVAL,
582238825Smm	    "Invalid string table");
583238825Smm	free(ar->strtab);
584238825Smm	ar->strtab = NULL;
585238825Smm	return (ARCHIVE_FATAL);
586238825Smm}
587238825Smm
588238825Smmstatic uint64_t
589238825Smmar_atol8(const char *p, unsigned char_cnt)
590238825Smm{
591238825Smm	uint64_t l, limit, last_digit_limit;
592238825Smm	unsigned int digit, base;
593238825Smm
594238825Smm	base = 8;
595238825Smm	limit = UINT64_MAX / base;
596238825Smm	last_digit_limit = UINT64_MAX % base;
597238825Smm
598238825Smm	while ((*p == ' ' || *p == '\t') && char_cnt-- > 0)
599238825Smm		p++;
600238825Smm
601238825Smm	l = 0;
602238825Smm	digit = *p - '0';
603238825Smm	while (*p >= '0' && digit < base  && char_cnt-- > 0) {
604238825Smm		if (l>limit || (l == limit && digit > last_digit_limit)) {
605238825Smm			l = UINT64_MAX; /* Truncate on overflow. */
606238825Smm			break;
607238825Smm		}
608238825Smm		l = (l * base) + digit;
609302001Smm		digit = *++p - '0';
610238825Smm	}
611238825Smm	return (l);
612238825Smm}
613238825Smm
614238825Smmstatic uint64_t
615238825Smmar_atol10(const char *p, unsigned char_cnt)
616238825Smm{
617238825Smm	uint64_t l, limit, last_digit_limit;
618238825Smm	unsigned int base, digit;
619238825Smm
620238825Smm	base = 10;
621238825Smm	limit = UINT64_MAX / base;
622238825Smm	last_digit_limit = UINT64_MAX % base;
623238825Smm
624238825Smm	while ((*p == ' ' || *p == '\t') && char_cnt-- > 0)
625238825Smm		p++;
626238825Smm	l = 0;
627302001Smm	digit = *p - '0';
628302001Smm	while (*p >= '0' && digit < base  && char_cnt-- > 0) {
629302001Smm		if (l > limit || (l == limit && digit > last_digit_limit)) {
630302001Smm			l = UINT64_MAX; /* Truncate on overflow. */
631302001Smm			break;
632302001Smm		}
633238825Smm		l = (l * base) + digit;
634238825Smm		digit = *++p - '0';
635238825Smm	}
636238825Smm	return (l);
637238825Smm}
638238825Smm