From 7ab411dbd2cb066652f5f51a1bc6cc793b7cafad Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Fri, 13 Dec 2019 13:52:33 +0100 Subject: Make the PAX header parser more strict Actually parse the length field and insist it matches the line length, then use the length field to advance to the next line. Signed-off-by: David Oberhollenzer --- lib/tar/read_header.c | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) (limited to 'lib/tar') diff --git a/lib/tar/read_header.c b/lib/tar/read_header.c index 7ec1333..845afc3 100644 --- a/lib/tar/read_header.c +++ b/lib/tar/read_header.c @@ -80,29 +80,45 @@ static int read_pax_header(FILE *fp, sqfs_u64 entsize, unsigned int *set_by_pax, sparse_map_t *sparse_last = NULL, *sparse; sqfs_u64 field, offset = 0, num_bytes = 0; char *buffer, *line, *key, *ptr, *value; + sqfs_u64 i, start, len; tar_xattr_t *xattr; - sqfs_u64 i; + int digit; buffer = record_to_memory(fp, entsize); if (buffer == NULL) return -1; - for (i = 0; i < entsize; ++i) { - while (i < entsize && isspace(buffer[i])) - ++i; - while (i < entsize && isdigit(buffer[i])) - ++i; + for (i = 0; i < entsize; i += len) { + start = i; + + if (!isdigit(buffer[i])) + goto fail_malformed; + + for (len = 0; i < entsize && isdigit(buffer[i]); ++i) { + digit = buffer[i] - '0'; + + if (len > (entsize - digit) / 10) + goto fail_ov; + + len = len * 10 + digit; + } + + if (!isspace(buffer[i])) + goto fail_malformed; + while (i < entsize && isspace(buffer[i])) ++i; - if (i >= entsize) - break; - line = buffer + i; + if (i >= entsize || (i - start) >= len) + goto fail_ov; - while (i < entsize && buffer[i] != '\n') - ++i; + len -= i - start; - buffer[i] = '\0'; + if (i + len > entsize) + goto fail_ov; + + line = buffer + i; + line[len - 1] = '\0'; if (!strncmp(line, "uid=", 4)) { if (pax_read_decimal(line + 4, &field)) @@ -214,6 +230,12 @@ static int read_pax_header(FILE *fp, sqfs_u64 entsize, unsigned int *set_by_pax, free(buffer); return 0; +fail_malformed: + fputs("Found a malformed PAX header.\n", stderr); + goto fail; +fail_ov: + fputs("Numeric overflow in PAX header.\n", stderr); + goto fail; fail_errno: perror("reading pax header"); goto fail; -- cgit v1.2.3