Hash :
af9692ba
Author :
Date :
2018-10-29T17:19:58
strntol: fix out-of-bounds read when skipping leading spaces The `git__strntol` family of functions accepts leading spaces and will simply skip them. The skipping will not honor the provided buffer's length, though, which may lead it to read outside of the provided buffer's bounds if it is not a simple NUL-terminated string. Furthermore, if leading space is trimmed, the function will further advance the pointer but not update the number of remaining bytes, which may also lead to out-of-bounds reads. Fix the issue by properly paying attention to the buffer length and updating it when stripping leading whitespace characters. Add a test that verifies that we won't read past the provided buffer length.
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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
#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__base_autodetection(void)
{
assert_l64_parses("0", 0, 0);
assert_l64_parses("00", 0, 0);
assert_l64_parses("0x", 0, 0);
assert_l64_parses("0foobar", 0, 0);
assert_l64_parses("07", 7, 0);
assert_l64_parses("017", 15, 0);
assert_l64_parses("0x8", 8, 0);
assert_l64_parses("0x18", 24, 0);
}
void test_core_strtol__buffer_length_with_autodetection_truncates(void)
{
int64_t i64;
cl_git_pass(git__strntol64(&i64, "011", 2, NULL, 0));
cl_assert_equal_i(i64, 1);
cl_git_pass(git__strntol64(&i64, "0x11", 3, NULL, 0));
cl_assert_equal_i(i64, 1);
}
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__buffer_length_with_leading_ws_truncates(void)
{
int64_t i64;
cl_git_fail(git__strntol64(&i64, " 1", 1, NULL, 10));
cl_git_pass(git__strntol64(&i64, " 11", 2, NULL, 10));
cl_assert_equal_i(i64, 1);
}
void test_core_strtol__buffer_length_with_leading_sign_truncates(void)
{
int64_t i64;
cl_git_fail(git__strntol64(&i64, "-1", 1, NULL, 10));
cl_git_pass(git__strntol64(&i64, "-11", 2, 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);
}