summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2018-10-29 17:19:58 +0100
committerEdward Thomson <ethomson@edwardthomson.com>2019-01-25 17:43:17 +0000
commitaf9692ba08daf1b384377966af063f5aa4748c72 (patch)
tree342cb141a010ef088ccd77559070220c2c02e31e
parent6daeb4fb72572733ba8d258a94443de267fc90e4 (diff)
downloadlibgit2-af9692ba08daf1b384377966af063f5aa4748c72.tar.gz
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.
-rw-r--r--src/util.c7
-rw-r--r--tests/core/strtol.c10
2 files changed, 15 insertions, 2 deletions
diff --git a/src/util.c b/src/util.c
index 911921857..62c06218c 100644
--- a/src/util.c
+++ b/src/util.c
@@ -83,8 +83,11 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha
/*
* White space
*/
- while (git__isspace(*p))
- p++;
+ while (nptr_len && git__isspace(*p))
+ p++, nptr_len--;
+
+ if (!nptr_len)
+ goto Return;
/*
* Sign
diff --git a/tests/core/strtol.c b/tests/core/strtol.c
index ba79fba51..ac19a2808 100644
--- a/tests/core/strtol.c
+++ b/tests/core/strtol.c
@@ -76,6 +76,16 @@ void test_core_strtol__buffer_length_truncates(void)
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__error_message_cuts_off(void)
{
assert_l32_fails("2147483657foobar", 10);