From 0c9a29f22e26c84c5049f5d9eeb5ae5bc722fde8 Mon Sep 17 00:00:00 2001 From: Brian Weaver Date: Wed, 26 Sep 2012 11:45:52 -0400 Subject: [PATCH] Refactored common code into a single function The tar_atol8() and tar_atol10() functions were essentially identical. The code has been refactored to a common function with tar_atol8() and tar_atol10() calling the commont function with the radix instead duplicating the code. The logic was also changed slightly to prevent a pointer dereference when a zero length character array is passed to the conversion routine. --- libarchive/archive_read_support_format_tar.c | 55 +++++--------------- 1 file changed, 13 insertions(+), 42 deletions(-) diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index ed5799333..8f5059767 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -2407,16 +2407,18 @@ tar_atol(const char *p, unsigned char_cnt) * it does obey locale. */ static int64_t -tar_atol8(const char *p, unsigned char_cnt) +tar_atol_base_n(const char *p, unsigned char_cnt, int base) { int64_t l, limit, last_digit_limit; - int digit, sign, base; + int digit, sign; - base = 8; limit = INT64_MAX / base; last_digit_limit = INT64_MAX % base; - while ((*p == ' ' || *p == '\t') && char_cnt != 0) { + /* the pointer will not be dereferenced if char_cnt is zero + * due to the way the && operator is evaulated. + */ + while (char_cnt != 0 && (*p == ' ' || *p == '\t')) { p++; char_cnt--; } @@ -2444,47 +2446,16 @@ tar_atol8(const char *p, unsigned char_cnt) return (sign < 0) ? -l : l; } -/* - * Note that this implementation does not (and should not!) obey - * locale settings; you cannot simply substitute strtol here, since - * it does obey locale. - */ static int64_t -tar_atol10(const char *p, unsigned char_cnt) +tar_atol8(const char *p, unsigned char_cnt) { - int64_t l, limit, last_digit_limit; - int base, digit, sign; - - base = 10; - limit = INT64_MAX / base; - last_digit_limit = INT64_MAX % base; - - while ((*p == ' ' || *p == '\t') && char_cnt != 0) { - p++; - char_cnt--; - } - - sign = 1; - if (char_cnt != 0 && *p == '-') { - sign = -1; - p++; - char_cnt--; - } + return tar_atol_base_n(p, char_cnt, 8); +} - l = 0; - if (char_cnt != 0) { - digit = *p - '0'; - while (digit >= 0 && digit < base && char_cnt != 0) { - if (l > limit || (l == limit && digit > last_digit_limit)) { - l = INT64_MAX; /* Truncate on overflow. */ - break; - } - l = (l * base) + digit; - digit = *++p - '0'; - char_cnt--; - } - } - return (sign < 0) ? -l : l; +static int64_t +tar_atol10(const char *p, unsigned char_cnt) +{ + return tar_atol_base_n(p, char_cnt, 10); } /* -- 2.47.3