diff options
author | Patrick Steinhardt <ps@pks.im> | 2018-10-25 11:21:14 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-25 11:21:14 +0200 |
commit | bea65980c7a42e34edfafbdc40b199ba7b2a564e (patch) | |
tree | 0d2e8e646b4c8f6ecff728c03a3fc3652eb3238f | |
parent | 1194546138cbbe3d822e4df2a41179a847099e75 (diff) | |
parent | ea19efc19fa683d632af3e172868bc4350724813 (diff) | |
download | libgit2-bea65980c7a42e34edfafbdc40b199ba7b2a564e.tar.gz |
Merge pull request #4851 from pks-t/pks/strtol-removal
strtol removal
-rw-r--r-- | src/commit_list.c | 4 | ||||
-rw-r--r-- | src/config.c | 2 | ||||
-rw-r--r-- | src/index.c | 2 | ||||
-rw-r--r-- | src/rebase.c | 2 | ||||
-rw-r--r-- | src/revparse.c | 5 | ||||
-rw-r--r-- | src/signature.c | 6 | ||||
-rw-r--r-- | src/streams/curl.c | 2 | ||||
-rw-r--r-- | src/transports/smart_pkt.c | 2 | ||||
-rw-r--r-- | src/transports/winhttp.c | 3 | ||||
-rw-r--r-- | src/tree-cache.c | 4 | ||||
-rw-r--r-- | src/util.c | 38 | ||||
-rw-r--r-- | src/util.h | 2 | ||||
-rw-r--r-- | tests/core/strtol.c | 105 |
13 files changed, 111 insertions, 66 deletions
diff --git a/src/commit_list.c b/src/commit_list.c index 96bd9dc15..b4313eed2 100644 --- a/src/commit_list.c +++ b/src/commit_list.c @@ -171,7 +171,9 @@ static int commit_quick_parse( buffer--; } - if ((buffer == committer_start) || (git__strtol64(&commit_time, (char *)(buffer + 1), NULL, 10) < 0)) + if ((buffer == committer_start) || + (git__strntol64(&commit_time, (char *)(buffer + 1), + buffer_end - buffer + 1, NULL, 10) < 0)) return commit_error(commit, "cannot parse commit time"); commit->time = commit_time; diff --git a/src/config.c b/src/config.c index 8d2e12f98..0837500f5 100644 --- a/src/config.c +++ b/src/config.c @@ -1300,7 +1300,7 @@ int git_config_parse_int64(int64_t *out, const char *value) const char *num_end; int64_t num; - if (!value || git__strtol64(&num, value, &num_end, 0) < 0) + if (!value || git__strntol64(&num, value, strlen(value), &num_end, 0) < 0) goto fail_parse; switch (*num_end) { diff --git a/src/index.c b/src/index.c index 465efaa4e..8858d23a1 100644 --- a/src/index.c +++ b/src/index.c @@ -2243,7 +2243,7 @@ static int read_reuc(git_index *index, const char *buffer, size_t size) for (i = 0; i < 3; i++) { int64_t tmp; - if (git__strtol64(&tmp, buffer, &endptr, 8) < 0 || + if (git__strntol64(&tmp, buffer, size, &endptr, 8) < 0 || !endptr || endptr == buffer || *endptr || tmp < 0 || tmp > UINT32_MAX) { index_entry_reuc_free(lost); diff --git a/src/rebase.c b/src/rebase.c index bc3c5995c..6503e5fc5 100644 --- a/src/rebase.c +++ b/src/rebase.c @@ -152,7 +152,7 @@ GIT_INLINE(int) rebase_readint( if ((error = rebase_readfile(asc_out, state_path, filename)) < 0) return error; - if (git__strtol32(&num, asc_out->ptr, &eol, 10) < 0 || num < 0 || *eol) { + if (git__strntol32(&num, asc_out->ptr, asc_out->size, &eol, 10) < 0 || num < 0 || *eol) { giterr_set(GITERR_REBASE, "the file '%s' contains an invalid numeric value", filename); return -1; } diff --git a/src/revparse.c b/src/revparse.c index bdbf87558..df96f9d86 100644 --- a/src/revparse.c +++ b/src/revparse.c @@ -128,7 +128,8 @@ static int try_parse_numeric(int *n, const char *curly_braces_content) int32_t content; const char *end_ptr; - if (git__strtol32(&content, curly_braces_content, &end_ptr, 10) < 0) + if (git__strntol32(&content, curly_braces_content, strlen(curly_braces_content), + &end_ptr, 10) < 0) return -1; if (*end_ptr != '\0') @@ -578,7 +579,7 @@ static int extract_how_many(int *n, const char *spec, size_t *pos) } while (spec[(*pos)] == kind && kind == '~'); if (git__isdigit(spec[*pos])) { - if (git__strtol32(&parsed, spec + *pos, &end_ptr, 10) < 0) + if (git__strntol32(&parsed, spec + *pos, strlen(spec + *pos), &end_ptr, 10) < 0) return GIT_EINVALIDSPEC; accumulated += (parsed - 1); diff --git a/src/signature.c b/src/signature.c index 286d0a618..91864bb88 100644 --- a/src/signature.c +++ b/src/signature.c @@ -231,7 +231,8 @@ int git_signature__parse(git_signature *sig, const char **buffer_out, const char *time_start = email_end + 2; const char *time_end; - if (git__strtol64(&sig->when.time, time_start, &time_end, 10) < 0) { + if (git__strntol64(&sig->when.time, time_start, + buffer_end - time_start, &time_end, 10) < 0) { git__free(sig->name); git__free(sig->email); sig->name = sig->email = NULL; @@ -246,7 +247,8 @@ int git_signature__parse(git_signature *sig, const char **buffer_out, tz_start = time_end + 1; if ((tz_start[0] != '-' && tz_start[0] != '+') || - git__strtol32(&offset, tz_start + 1, &tz_end, 10) < 0) { + git__strntol32(&offset, tz_start + 1, + buffer_end - tz_start + 1, &tz_end, 10) < 0) { /* malformed timezone, just assume it's zero */ offset = 0; } diff --git a/src/streams/curl.c b/src/streams/curl.c index ee13be1dc..3c0af3b04 100644 --- a/src/streams/curl.c +++ b/src/streams/curl.c @@ -330,7 +330,7 @@ int git_curl_stream_new(git_stream **out, const char *host, const char *port) return -1; } - if ((error = git__strtol32(&iport, port, NULL, 10)) < 0) { + if ((error = git__strntol32(&iport, port, strlen(port), NULL, 10)) < 0) { git__free(st); return error; } diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c index 6a404efe4..fb59c70ec 100644 --- a/src/transports/smart_pkt.c +++ b/src/transports/smart_pkt.c @@ -391,7 +391,7 @@ static int parse_len(size_t *out, const char *line, size_t linelen) } } - if ((error = git__strtol32(&len, num, &num_end, 16)) < 0) + if ((error = git__strntol32(&len, num, PKT_LEN_SIZE, &num_end, 16)) < 0) return error; if (len < 0) diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c index 3df892d09..e925dbdc0 100644 --- a/src/transports/winhttp.c +++ b/src/transports/winhttp.c @@ -766,7 +766,8 @@ static int winhttp_connect( t->connection = NULL; /* Prepare port */ - if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0) + if (git__strntol32(&port, t->connection_data.port, + strlen(t->connection_data.port), NULL, 10) < 0) return -1; /* Prepare host */ diff --git a/src/tree-cache.c b/src/tree-cache.c index b331d22a2..c33e6af9e 100644 --- a/src/tree-cache.c +++ b/src/tree-cache.c @@ -91,7 +91,7 @@ static int read_tree_internal(git_tree_cache **out, return -1; /* Blank-terminated ASCII decimal number of entries in this tree */ - if (git__strtol32(&count, buffer, &buffer, 10) < 0) + if (git__strntol32(&count, buffer, buffer_end - buffer, &buffer, 10) < 0) goto corrupted; tree->entry_count = count; @@ -100,7 +100,7 @@ static int read_tree_internal(git_tree_cache **out, goto corrupted; /* Number of children of the tree, newline-terminated */ - if (git__strtol32(&count, buffer, &buffer, 10) < 0 || count < 0) + if (git__strntol32(&count, buffer, buffer_end - buffer, &buffer, 10) < 0 || count < 0) goto corrupted; tree->children_count = count; diff --git a/src/util.c b/src/util.c index 79b362f7f..20c88a1d3 100644 --- a/src/util.c +++ b/src/util.c @@ -68,12 +68,6 @@ int git_strarray_copy(git_strarray *tgt, const git_strarray *src) return 0; } -int git__strtol64(int64_t *result, const char *nptr, const char **endptr, int base) -{ - - return git__strntol64(result, nptr, (size_t)-1, endptr, base); -} - int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base) { const char *p; @@ -132,10 +126,20 @@ int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const cha v = c - 'A' + 10; if (v >= base) break; - nn = n * base + (neg ? -v : v); - if ((!neg && nn < n) || (neg && nn > n)) + v = neg ? -v : v; + if (n > INT64_MAX / base || n < INT64_MIN / base) { ovfl = 1; - n = nn; + /* Keep on iterating until the end of this number */ + continue; + } + nn = n * base; + if ((v > 0 && nn > INT64_MAX - v) || + (v < 0 && nn < INT64_MIN - v)) { + ovfl = 1; + /* Keep on iterating until the end of this number */ + continue; + } + n = nn + v; } Return: @@ -156,28 +160,26 @@ Return: return 0; } -int git__strtol32(int32_t *result, const char *nptr, const char **endptr, int base) -{ - - return git__strntol32(result, nptr, (size_t)-1, endptr, base); -} - int git__strntol32(int32_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base) { - int error; + const char *tmp_endptr; int32_t tmp_int; int64_t tmp_long; + int error; - if ((error = git__strntol64(&tmp_long, nptr, nptr_len, endptr, base)) < 0) + if ((error = git__strntol64(&tmp_long, nptr, nptr_len, &tmp_endptr, base)) < 0) return error; tmp_int = tmp_long & 0xFFFFFFFF; if (tmp_int != tmp_long) { - giterr_set(GITERR_INVALID, "failed to convert: '%s' is too large", nptr); + int len = tmp_endptr - nptr; + giterr_set(GITERR_INVALID, "failed to convert: '%.*s' is too large", len, nptr); return -1; } *result = tmp_int; + if (endptr) + *endptr = tmp_endptr; return error; } diff --git a/src/util.h b/src/util.h index b6f5b7519..400024373 100644 --- a/src/util.h +++ b/src/util.h @@ -58,9 +58,7 @@ GIT_INLINE(int) git__signum(int val) return ((val > 0) - (val < 0)); } -extern int git__strtol32(int32_t *n, const char *buff, const char **end_buf, int base); extern int git__strntol32(int32_t *n, const char *buff, size_t buff_len, const char **end_buf, int base); -extern int git__strtol64(int64_t *n, const char *buff, const char **end_buf, int base); extern int git__strntol64(int64_t *n, const char *buff, size_t buff_len, const char **end_buf, int base); diff --git a/tests/core/strtol.c b/tests/core/strtol.c index 0d3b6a5e6..ba79fba51 100644 --- a/tests/core/strtol.c +++ b/tests/core/strtol.c @@ -1,45 +1,84 @@ #include "clar_libgit2.h" -void test_core_strtol__int32(void) +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); +} - cl_git_pass(git__strtol32(&i, "123", NULL, 10)); - cl_assert(i == 123); - cl_git_pass(git__strtol32(&i, " +123 ", NULL, 10)); - cl_assert(i == 123); - cl_git_pass(git__strtol32(&i, " +2147483647 ", NULL, 10)); - cl_assert(i == 2147483647); - cl_git_pass(git__strtol32(&i, " -2147483648 ", NULL, 10)); - cl_assert(i == -2147483648LL); - - cl_git_fail(git__strtol32(&i, " 2147483657 ", NULL, 10)); - cl_git_fail(git__strtol32(&i, " -2147483657 ", NULL, 10)); +static void assert_l32_fails(const char *string, int base) +{ + int32_t i; + cl_git_fail(git__strntol32(&i, string, strlen(string), NULL, base)); } -void test_core_strtol__int64(void) +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); - cl_git_pass(git__strtol64(&i, "123", NULL, 10)); - cl_assert(i == 123); - cl_git_pass(git__strtol64(&i, " +123 ", NULL, 10)); - cl_assert(i == 123); - cl_git_pass(git__strtol64(&i, " +2147483647 ", NULL, 10)); - cl_assert(i == 2147483647); - cl_git_pass(git__strtol64(&i, " -2147483648 ", NULL, 10)); - cl_assert(i == -2147483648LL); - cl_git_pass(git__strtol64(&i, " 2147483657 ", NULL, 10)); - cl_assert(i == 2147483657LL); - cl_git_pass(git__strtol64(&i, " -2147483657 ", NULL, 10)); - cl_assert(i == -2147483657LL); - cl_git_pass(git__strtol64(&i, " 9223372036854775807 ", NULL, 10)); - cl_assert(i == INT64_MAX); - cl_git_pass(git__strtol64(&i, " -9223372036854775808 ", NULL, 10)); - cl_assert(i == INT64_MIN); - cl_git_pass(git__strtol64(&i, " 0x7fffffffffffffff ", NULL, 16)); - cl_assert(i == INT64_MAX); - cl_git_pass(git__strtol64(&i, " -0x8000000000000000 ", NULL, 16)); - cl_assert(i == INT64_MIN); + 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); +} |