Skip to content

Commit 9189a66

Browse files
authored
Merge pull request libgit2#4886 from pks-t/pks/strntol-truncate-leading-sign
strntol: fix out-of-bounds reads when parsing numbers with leading sign
2 parents fd4e3b2 + 4b84db6 commit 9189a66

File tree

3 files changed

+18
-22
lines changed

3 files changed

+18
-22
lines changed

src/patch_parse.c

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -458,26 +458,6 @@ static int parse_header_git(
458458
return error;
459459
}
460460

461-
static int parse_number(git_off_t *out, git_patch_parse_ctx *ctx)
462-
{
463-
const char *end;
464-
int64_t num;
465-
466-
if (!git__isdigit(ctx->parse_ctx.line[0]))
467-
return -1;
468-
469-
if (git__strntol64(&num, ctx->parse_ctx.line, ctx->parse_ctx.line_len, &end, 10) < 0)
470-
return -1;
471-
472-
if (num < 0)
473-
return -1;
474-
475-
*out = num;
476-
git_parse_advance_chars(&ctx->parse_ctx, (end - ctx->parse_ctx.line));
477-
478-
return 0;
479-
}
480-
481461
static int parse_int(int *out, git_patch_parse_ctx *ctx)
482462
{
483463
git_off_t num;

src/util.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,15 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha
9292
/*
9393
* Sign
9494
*/
95-
if (*p == '-' || *p == '+')
96-
if (*p++ == '-')
95+
if (*p == '-' || *p == '+') {
96+
if (*p == '-')
9797
neg = 1;
98+
p++;
99+
nptr_len--;
100+
}
101+
102+
if (!nptr_len)
103+
goto Return;
98104

99105
/*
100106
* Automatically detect the base if none was given to us.

tests/core/strtol.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,16 @@ void test_core_strtol__buffer_length_with_leading_ws_truncates(void)
108108
cl_assert_equal_i(i64, 1);
109109
}
110110

111+
void test_core_strtol__buffer_length_with_leading_sign_truncates(void)
112+
{
113+
int64_t i64;
114+
115+
cl_git_fail(git__strntol64(&i64, "-1", 1, NULL, 10));
116+
117+
cl_git_pass(git__strntol64(&i64, "-11", 2, NULL, 10));
118+
cl_assert_equal_i(i64, -1);
119+
}
120+
111121
void test_core_strtol__error_message_cuts_off(void)
112122
{
113123
assert_l32_fails("2147483657foobar", 10);

0 commit comments

Comments
 (0)