threads / patch / 42765

patchconfig.c: fix potential number truncation in git_parse_signed()

Subject: [PATCH] config.c: fix potential number truncation in git_parse_signed()

## tl;dr

3 messages between Jul 2, 2016 and Jul 8, 2016. Diffs are folded; open one to read it.

replies: 2people: 2as markdown or json

Nguyễn Thái Ngọc Duy· Jul 2, 2016, 13:13 UTC · lore

clang -Wabsolute-value on IA-32 architecture complains that "absolute value function 'labs' given an argument of type 'intmax_t' (aka 'long long') but has parameter of type 'long' which may cause truncation of value". Very unlikely for this code though. Nevertheless, add an explicit check for truncation to shut clang up and error out.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 config.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
Show changes to config.c +8 −2
diff --git a/config.c b/config.c
index d7ce34b..880bd4a 100644
--- a/config.c
+++ b/config.c
@@ -503,6 +503,7 @@ static int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
 		intmax_t val;
 		uintmax_t uval;
 		uintmax_t factor = 1;
+		long int lival;
 
 		errno = 0;
 		val = strtoimax(value, &end, 0);
@@ -512,9 +513,14 @@ static int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
 			errno = EINVAL;
 			return 0;
 		}
-		uval = labs(val);
+		lival = (long int)val;
+		if (lival != val) {
+			errno = ERANGE;
+			return 0;
+		}
+		uval = labs(lival);
 		uval *= factor;
-		if (uval > max || labs(val) > uval) {
+		if (uval > max || labs(lival) > uval) {
 			errno = ERANGE;
 			return 0;
 		}
-- 
2.8.2.532.g6dfa503.dirty
Junio C Hamano· Jul 6, 2016, 19:33 UTC · re: Nguyễn Thái Ngọc Duy · lore

Re: [PATCH] config.c: fix potential number truncation in git_parse_signed()

Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:
Show 5 quoted lines
> clang -Wabsolute-value on IA-32 architecture complains that "absolute
> value function 'labs' given an argument of type 'intmax_t' (aka 'long
> long') but has parameter of type 'long' which may cause truncation of
> value". Very unlikely for this code though. Nevertheless, add an
> explicit check for truncation to shut clang up and error out.

Thanks. It however makes me wonder if it is a better approach to avoid downcasting intmax_t to long by using imaxabs()?

Show 35 quoted lines
>
> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> ---
>  config.c | 10 ++++++++--
>  1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/config.c b/config.c
> index d7ce34b..880bd4a 100644
> --- a/config.c
> +++ b/config.c
> @@ -503,6 +503,7 @@ static int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
>  		intmax_t val;
>  		uintmax_t uval;
>  		uintmax_t factor = 1;
> +		long int lival;
>  
>  		errno = 0;
>  		val = strtoimax(value, &end, 0);
> @@ -512,9 +513,14 @@ static int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
>  			errno = EINVAL;
>  			return 0;
>  		}
> -		uval = labs(val);
> +		lival = (long int)val;
> +		if (lival != val) {
> +			errno = ERANGE;
> +			return 0;
> +		}
> +		uval = labs(lival);
>  		uval *= factor;
> -		if (uval > max || labs(val) > uval) {
> +		if (uval > max || labs(lival) > uval) {
>  			errno = ERANGE;
>  			return 0;
>  		}
Duy Nguyen· Jul 8, 2016, 16:01 UTC · re: Junio C Hamano · lore

Re: [PATCH] config.c: fix potential number truncation in git_parse_signed()

On Wed, Jul 6, 2016 at 9:33 PM, Junio C Hamano <gitster@pobox.com> wrote:
Show 10 quoted lines
> Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:
>
>> clang -Wabsolute-value on IA-32 architecture complains that "absolute
>> value function 'labs' given an argument of type 'intmax_t' (aka 'long
>> long') but has parameter of type 'long' which may cause truncation of
>> value". Very unlikely for this code though. Nevertheless, add an
>> explicit check for truncation to shut clang up and error out.
>
> Thanks.  It however makes me wonder if it is a better approach to
> avoid downcasting intmax_t to long by using imaxabs()?

I think the tricky part is detect overflow. WIth uval being a potentially signed number, i'm not sure how to catch it. The (uval > max || labs(val) > uval) was written with unsigned number in mind, I think.

Show 36 quoted lines
>
>>
>> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
>> ---
>>  config.c | 10 ++++++++--
>>  1 file changed, 8 insertions(+), 2 deletions(-)
>>
>> diff --git a/config.c b/config.c
>> index d7ce34b..880bd4a 100644
>> --- a/config.c
>> +++ b/config.c
>> @@ -503,6 +503,7 @@ static int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
>>               intmax_t val;
>>               uintmax_t uval;
>>               uintmax_t factor = 1;
>> +             long int lival;
>>
>>               errno = 0;
>>               val = strtoimax(value, &end, 0);
>> @@ -512,9 +513,14 @@ static int git_parse_signed(const char *value, intmax_t *ret, intmax_t max)
>>                       errno = EINVAL;
>>                       return 0;
>>               }
>> -             uval = labs(val);
>> +             lival = (long int)val;
>> +             if (lival != val) {
>> +                     errno = ERANGE;
>> +                     return 0;
>> +             }
>> +             uval = labs(lival);
>>               uval *= factor;
>> -             if (uval > max || labs(val) > uval) {
>> +             if (uval > max || labs(lival) > uval) {
>>                       errno = ERANGE;
>>                       return 0;
>>               }
-- 
Duy

← back to recent threads