Hash :
ea19efc1
Author :
Date :
2018-10-18T15:08:56
util: fix out of bounds read in error message When an integer that is parsed with `git__strntol32` is too big to fit into an int32, we will generate an error message that includes the actual string that failed to parse. This does not acknowledge the fact that the string may either not be NUL terminated or alternative include additional characters after the number that is to be parsed. We may thus end up printing characters into the buffer that aren't the number or, worse, read out of bounds. Fix the issue by utilizing the `endptr` that was set by `git__strntol64`. This pointer is guaranteed to be set to the first character following the number, and we can thus use it to compute the width of the number that shall be printed. Create a test to verify that we correctly truncate the number.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
#include "clar_libgit2.h"
static void assert_l32_parses(const char *string, int32_t expected, int base)
{
int32_t i;
cl_git_pass(git__strntol32(&i, string, strlen(string), NULL, base));
cl_assert_equal_i(i, expected);
}
static void assert_l32_fails(const char *string, int base)
{
int32_t i;
cl_git_fail(git__strntol32(&i, string, strlen(string), NULL, base));
}
static void assert_l64_parses(const char *string, int64_t expected, int base)
{
int64_t i;
cl_git_pass(git__strntol64(&i, string, strlen(string), NULL, base));
cl_assert_equal_i(i, expected);
}
static void assert_l64_fails(const char *string, int base)
{
int64_t i;
cl_git_fail(git__strntol64(&i, string, strlen(string), NULL, base));
}
void test_core_strtol__int32(void)
{
assert_l32_parses("123", 123, 10);
assert_l32_parses(" +123 ", 123, 10);
assert_l32_parses(" +2147483647 ", 2147483647, 10);
assert_l32_parses(" -2147483648 ", -2147483648LL, 10);
assert_l32_parses("A", 10, 16);
assert_l32_parses("1x1", 1, 10);
assert_l32_fails("", 10);
assert_l32_fails("a", 10);
assert_l32_fails("x10x", 10);
assert_l32_fails(" 2147483657 ", 10);
assert_l32_fails(" -2147483657 ", 10);
}
void test_core_strtol__int64(void)
{
assert_l64_parses("123", 123, 10);
assert_l64_parses(" +123 ", 123, 10);
assert_l64_parses(" +2147483647 ", 2147483647, 10);
assert_l64_parses(" -2147483648 ", -2147483648LL, 10);
assert_l64_parses(" 2147483657 ", 2147483657LL, 10);
assert_l64_parses(" -2147483657 ", -2147483657LL, 10);
assert_l64_parses(" 9223372036854775807 ", INT64_MAX, 10);
assert_l64_parses(" -9223372036854775808 ", INT64_MIN, 10);
assert_l64_parses(" 0x7fffffffffffffff ", INT64_MAX, 16);
assert_l64_parses(" -0x8000000000000000 ", INT64_MIN, 16);
assert_l64_parses("1a", 26, 16);
assert_l64_parses("1A", 26, 16);
assert_l64_fails("", 10);
assert_l64_fails("a", 10);
assert_l64_fails("x10x", 10);
assert_l64_fails("0x8000000000000000", 16);
assert_l64_fails("-0x8000000000000001", 16);
}
void test_core_strtol__buffer_length_truncates(void)
{
int32_t i32;
int64_t i64;
cl_git_pass(git__strntol32(&i32, "11", 1, NULL, 10));
cl_assert_equal_i(i32, 1);
cl_git_pass(git__strntol64(&i64, "11", 1, NULL, 10));
cl_assert_equal_i(i64, 1);
}
void test_core_strtol__error_message_cuts_off(void)
{
assert_l32_fails("2147483657foobar", 10);
cl_assert(strstr(giterr_last()->message, "2147483657") != NULL);
cl_assert(strstr(giterr_last()->message, "foobar") == NULL);
}