File libgit2-boo1114729.patch of Package libgit2.9827

diff -urpN libgit2-0.24.1.orig/src/commit.c libgit2-0.24.1/src/commit.c
--- libgit2-0.24.1.orig/src/commit.c	2018-11-30 12:33:48.857715432 -0600
+++ libgit2-0.24.1/src/commit.c	2018-12-03 16:48:07.486679807 -0600
@@ -390,7 +390,7 @@ int git_commit__parse(void *_commit, git
 		while (eoln < buffer_end && *eoln != '\n')
 			++eoln;
 
-		if (git__prefixcmp(buffer, "encoding ") == 0) {
+		if (git__prefixncmp(buffer, buffer_end - buffer, "encoding ") == 0) {
 			buffer += strlen("encoding ");
 
 			commit->message_encoding = git__strndup(buffer, eoln - buffer);
diff -urpN libgit2-0.24.1.orig/src/commit_list.c libgit2-0.24.1/src/commit_list.c
--- libgit2-0.24.1.orig/src/commit_list.c	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/src/commit_list.c	2018-11-30 17:57:07.753226873 -0600
@@ -166,7 +166,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 -urpN libgit2-0.24.1.orig/src/config.c libgit2-0.24.1/src/config.c
--- libgit2-0.24.1.orig/src/config.c	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/src/config.c	2018-11-30 18:09:06.077051245 -0600
@@ -1279,7 +1279,7 @@ int git_config_parse_int64(int64_t *out,
 	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 -urpN libgit2-0.24.1.orig/src/curl_stream.c libgit2-0.24.1/src/curl_stream.c
--- libgit2-0.24.1.orig/src/curl_stream.c	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/src/curl_stream.c	2018-12-03 15:55:59.292894819 -0600
@@ -212,7 +212,7 @@ int git_curl_stream_new(git_stream **out
 		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 -urpN libgit2-0.24.1.orig/src/index.c libgit2-0.24.1/src/index.c
--- libgit2-0.24.1.orig/src/index.c	2018-11-30 13:50:00.592636745 -0600
+++ libgit2-0.24.1/src/index.c	2018-11-30 17:58:02.081515708 -0600
@@ -2181,7 +2181,7 @@ static int read_reuc(git_index *index, c
 		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) {
 				index_entry_reuc_free(lost);
diff -urpN libgit2-0.24.1.orig/src/rebase.c libgit2-0.24.1/src/rebase.c
--- libgit2-0.24.1.orig/src/rebase.c	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/src/rebase.c	2018-12-03 16:23:13.063866526 -0600
@@ -151,7 +151,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 -urpN libgit2-0.24.1.orig/src/revparse.c libgit2-0.24.1/src/revparse.c
--- libgit2-0.24.1.orig/src/revparse.c	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/src/revparse.c	2018-12-03 15:55:59.292894819 -0600
@@ -127,7 +127,8 @@ static int try_parse_numeric(int *n, con
 	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')
@@ -577,7 +578,7 @@ static int extract_how_many(int *n, cons
 		} 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 -urpN libgit2-0.24.1.orig/src/signature.c libgit2-0.24.1/src/signature.c
--- libgit2-0.24.1.orig/src/signature.c	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/src/signature.c	2018-12-04 09:45:16.286494537 -0600
@@ -227,7 +227,8 @@ int git_signature__parse(git_signature *
 		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)
 			return signature_error("invalid Unix timestamp");
 
 		/* do we have a timezone? */
@@ -238,8 +239,9 @@ int git_signature__parse(git_signature *
 			tz_start = time_end + 1;
 
 			if ((tz_start[0] != '-' && tz_start[0] != '+') ||
-				git__strtol32(&offset, tz_start + 1, &tz_end, 10) < 0) {
-				//malformed timezone, just assume it's zero
+			    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 -urpN libgit2-0.24.1.orig/src/tag.c libgit2-0.24.1/src/tag.c
--- libgit2-0.24.1.orig/src/tag.c	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/src/tag.c	2018-12-03 16:29:43.489577620 -0600
@@ -70,10 +70,9 @@ static int tag_parse(git_tag *tag, const
 	static const char *tag_types[] = {
 		NULL, "commit\n", "tree\n", "blob\n", "tag\n"
 	};
-
-	unsigned int i;
 	size_t text_len, alloc_len;
-	char *search;
+	const char *search;
+	unsigned int i;
 
 	if (git_oid__parse(&tag->target, &buffer, buffer_end, "object ") < 0)
 		return tag_error("Object field invalid");
diff -urpN libgit2-0.24.1.orig/src/transports/http.c.orig libgit2-0.24.1/src/transports/http.c.orig
--- libgit2-0.24.1.orig/src/transports/http.c.orig	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/src/transports/http.c.orig	1969-12-31 18:00:00.000000000 -0600
@@ -1,1082 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-#ifndef GIT_WINHTTP
-
-#include "git2.h"
-#include "http_parser.h"
-#include "buffer.h"
-#include "netops.h"
-#include "global.h"
-#include "remote.h"
-#include "smart.h"
-#include "auth.h"
-#include "auth_negotiate.h"
-#include "tls_stream.h"
-#include "socket_stream.h"
-#include "curl_stream.h"
-
-git_http_auth_scheme auth_schemes[] = {
-	{ GIT_AUTHTYPE_NEGOTIATE, "Negotiate", GIT_CREDTYPE_DEFAULT, git_http_auth_negotiate },
-	{ GIT_AUTHTYPE_BASIC, "Basic", GIT_CREDTYPE_USERPASS_PLAINTEXT, git_http_auth_basic },
-};
-
-static const char *upload_pack_service = "upload-pack";
-static const char *upload_pack_ls_service_url = "/info/refs?service=git-upload-pack";
-static const char *upload_pack_service_url = "/git-upload-pack";
-static const char *receive_pack_service = "receive-pack";
-static const char *receive_pack_ls_service_url = "/info/refs?service=git-receive-pack";
-static const char *receive_pack_service_url = "/git-receive-pack";
-static const char *get_verb = "GET";
-static const char *post_verb = "POST";
-
-#define OWNING_SUBTRANSPORT(s) ((http_subtransport *)(s)->parent.subtransport)
-
-#define PARSE_ERROR_GENERIC	-1
-#define PARSE_ERROR_REPLAY	-2
-/** Look at the user field */
-#define PARSE_ERROR_EXT         -3
-
-#define CHUNK_SIZE	4096
-
-enum last_cb {
-	NONE,
-	FIELD,
-	VALUE
-};
-
-typedef struct {
-	git_smart_subtransport_stream parent;
-	const char *service;
-	const char *service_url;
-	char *redirect_url;
-	const char *verb;
-	char *chunk_buffer;
-	unsigned chunk_buffer_len;
-	unsigned sent_request : 1,
-		received_response : 1,
-		chunked : 1,
-		redirect_count : 3;
-} http_stream;
-
-typedef struct {
-	git_smart_subtransport parent;
-	transport_smart *owner;
-	git_stream *io;
-	gitno_connection_data connection_data;
-	bool connected;
-
-	/* Parser structures */
-	http_parser parser;
-	http_parser_settings settings;
-	gitno_buffer parse_buffer;
-	git_buf parse_header_name;
-	git_buf parse_header_value;
-	char parse_buffer_data[NETIO_BUFSIZE];
-	char *content_type;
-	char *location;
-	git_vector www_authenticate;
-	enum last_cb last_cb;
-	int parse_error;
-	int error;
-	unsigned parse_finished : 1;
-
-	/* Authentication */
-	git_cred *cred;
-	git_cred *url_cred;
-	git_vector auth_contexts;
-} http_subtransport;
-
-typedef struct {
-	http_stream *s;
-	http_subtransport *t;
-
-	/* Target buffer details from read() */
-	char *buffer;
-	size_t buf_size;
-	size_t *bytes_read;
-} parser_context;
-
-static bool credtype_match(git_http_auth_scheme *scheme, void *data)
-{
-	unsigned int credtype = *(unsigned int *)data;
-
-	return !!(scheme->credtypes & credtype);
-}
-
-static bool challenge_match(git_http_auth_scheme *scheme, void *data)
-{
-	const char *scheme_name = scheme->name;
-	const char *challenge = (const char *)data;
-	size_t scheme_len;
-
-	scheme_len = strlen(scheme_name);
-	return (strncmp(challenge, scheme_name, scheme_len) == 0 &&
-		(challenge[scheme_len] == '\0' || challenge[scheme_len] == ' '));
-}
-
-static int auth_context_match(
-	git_http_auth_context **out,
-	http_subtransport *t,
-	bool (*scheme_match)(git_http_auth_scheme *scheme, void *data),
-	void *data)
-{
-	git_http_auth_scheme *scheme = NULL;
-	git_http_auth_context *context = NULL, *c;
-	size_t i;
-
-	*out = NULL;
-
-	for (i = 0; i < ARRAY_SIZE(auth_schemes); i++) {
-		if (scheme_match(&auth_schemes[i], data)) {
-			scheme = &auth_schemes[i];
-			break;
-		}
-	}
-
-	if (!scheme)
-		return 0;
-
-	/* See if authentication has already started for this scheme */
-	git_vector_foreach(&t->auth_contexts, i, c) {
-		if (c->type == scheme->type) {
-			context = c;
-			break;
-		}
-	}
-
-	if (!context) {
-		if (scheme->init_context(&context, &t->connection_data) < 0)
-			return -1;
-		else if (!context)
-			return 0;
-		else if (git_vector_insert(&t->auth_contexts, context) < 0)
-			return -1;
-	}
-
-	*out = context;
-
-	return 0;
-}
-
-static int apply_credentials(git_buf *buf, http_subtransport *t)
-{
-	git_cred *cred = t->cred;
-	git_http_auth_context *context;
-
-	/* Apply the credentials given to us in the URL */
-	if (!cred && t->connection_data.user && t->connection_data.pass) {
-		if (!t->url_cred &&
-			git_cred_userpass_plaintext_new(&t->url_cred,
-				t->connection_data.user, t->connection_data.pass) < 0)
-			return -1;
-
-		cred = t->url_cred;
-	}
-
-	if (!cred)
-		return 0;
-
-	/* Get or create a context for the best scheme for this cred type */
-	if (auth_context_match(&context, t, credtype_match, &cred->credtype) < 0)
-		return -1;
-
-	return context->next_token(buf, context, cred);
-}
-
-static const char *user_agent(void)
-{
-	const char *custom = git_libgit2__user_agent();
-
-	if (custom)
-		return custom;
-
-	return "libgit2 " LIBGIT2_VERSION;
-}
-
-static int gen_request(
-	git_buf *buf,
-	http_stream *s,
-	size_t content_length)
-{
-	http_subtransport *t = OWNING_SUBTRANSPORT(s);
-	const char *path = t->connection_data.path ? t->connection_data.path : "/";
-	size_t i;
-
-	git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n", s->verb, path, s->service_url);
-
-	git_buf_printf(buf, "User-Agent: git/1.0 (%s)\r\n", user_agent());
-	git_buf_printf(buf, "Host: %s\r\n", t->connection_data.host);
-
-	if (s->chunked || content_length > 0) {
-		git_buf_printf(buf, "Accept: application/x-git-%s-result\r\n", s->service);
-		git_buf_printf(buf, "Content-Type: application/x-git-%s-request\r\n", s->service);
-
-		if (s->chunked)
-			git_buf_puts(buf, "Transfer-Encoding: chunked\r\n");
-		else
-			git_buf_printf(buf, "Content-Length: %"PRIuZ "\r\n", content_length);
-	} else
-		git_buf_puts(buf, "Accept: */*\r\n");
-
-	for (i = 0; i < t->owner->custom_headers.count; i++) {
-		if (t->owner->custom_headers.strings[i])
-			git_buf_printf(buf, "%s\r\n", t->owner->custom_headers.strings[i]);
-	}
-
-	/* Apply credentials to the request */
-	if (apply_credentials(buf, t) < 0)
-		return -1;
-
-	git_buf_puts(buf, "\r\n");
-
-	if (git_buf_oom(buf))
-		return -1;
-
-	return 0;
-}
-
-static int parse_authenticate_response(
-	git_vector *www_authenticate,
-	http_subtransport *t,
-	int *allowed_types)
-{
-	git_http_auth_context *context;
-	char *challenge;
-	size_t i;
-
-	git_vector_foreach(www_authenticate, i, challenge) {
-		if (auth_context_match(&context, t, challenge_match, challenge) < 0)
-			return -1;
-		else if (!context)
-			continue;
-
-		if (context->set_challenge &&
-			context->set_challenge(context, challenge) < 0)
-			return -1;
-
-		*allowed_types |= context->credtypes;
-	}
-
-	return 0;
-}
-
-static int on_header_ready(http_subtransport *t)
-{
-	git_buf *name = &t->parse_header_name;
-	git_buf *value = &t->parse_header_value;
-
-	if (!strcasecmp("Content-Type", git_buf_cstr(name))) {
-		if (!t->content_type) {
-			t->content_type = git__strdup(git_buf_cstr(value));
-			GITERR_CHECK_ALLOC(t->content_type);
-		}
-	}
-	else if (!strcasecmp("WWW-Authenticate", git_buf_cstr(name))) {
-		char *dup = git__strdup(git_buf_cstr(value));
-		GITERR_CHECK_ALLOC(dup);
-
-		git_vector_insert(&t->www_authenticate, dup);
-	}
-	else if (!strcasecmp("Location", git_buf_cstr(name))) {
-		if (!t->location) {
-			t->location = git__strdup(git_buf_cstr(value));
-			GITERR_CHECK_ALLOC(t->location);
-		}
-	}
-
-	return 0;
-}
-
-static int on_header_field(http_parser *parser, const char *str, size_t len)
-{
-	parser_context *ctx = (parser_context *) parser->data;
-	http_subtransport *t = ctx->t;
-
-	/* Both parse_header_name and parse_header_value are populated
-	 * and ready for consumption */
-	if (VALUE == t->last_cb)
-		if (on_header_ready(t) < 0)
-			return t->parse_error = PARSE_ERROR_GENERIC;
-
-	if (NONE == t->last_cb || VALUE == t->last_cb)
-		git_buf_clear(&t->parse_header_name);
-
-	if (git_buf_put(&t->parse_header_name, str, len) < 0)
-		return t->parse_error = PARSE_ERROR_GENERIC;
-
-	t->last_cb = FIELD;
-	return 0;
-}
-
-static int on_header_value(http_parser *parser, const char *str, size_t len)
-{
-	parser_context *ctx = (parser_context *) parser->data;
-	http_subtransport *t = ctx->t;
-
-	assert(NONE != t->last_cb);
-
-	if (FIELD == t->last_cb)
-		git_buf_clear(&t->parse_header_value);
-
-	if (git_buf_put(&t->parse_header_value, str, len) < 0)
-		return t->parse_error = PARSE_ERROR_GENERIC;
-
-	t->last_cb = VALUE;
-	return 0;
-}
-
-static int on_headers_complete(http_parser *parser)
-{
-	parser_context *ctx = (parser_context *) parser->data;
-	http_subtransport *t = ctx->t;
-	http_stream *s = ctx->s;
-	git_buf buf = GIT_BUF_INIT;
-	int error = 0, no_callback = 0, allowed_auth_types = 0;
-
-	/* Both parse_header_name and parse_header_value are populated
-	 * and ready for consumption. */
-	if (VALUE == t->last_cb)
-		if (on_header_ready(t) < 0)
-			return t->parse_error = PARSE_ERROR_GENERIC;
-
-	/* Capture authentication headers which may be a 401 (authentication
-	 * is not complete) or a 200 (simply informing us that auth *is*
-	 * complete.)
-	 */
-	if (parse_authenticate_response(&t->www_authenticate, t,
-			&allowed_auth_types) < 0)
-		return t->parse_error = PARSE_ERROR_GENERIC;
-
-	/* Check for an authentication failure. */
-	if (parser->status_code == 401 && get_verb == s->verb) {
-		if (!t->owner->cred_acquire_cb) {
-			no_callback = 1;
-		} else {
-			if (allowed_auth_types) {
-				if (t->cred) {
-					t->cred->free(t->cred);
-					t->cred = NULL;
-				}
-
-				error = t->owner->cred_acquire_cb(&t->cred,
-								  t->owner->url,
-								  t->connection_data.user,
-								  allowed_auth_types,
-								  t->owner->cred_acquire_payload);
-
-				if (error == GIT_PASSTHROUGH) {
-					no_callback = 1;
-				} else if (error < 0) {
-					t->error = error;
-					return t->parse_error = PARSE_ERROR_EXT;
-				} else {
-					assert(t->cred);
-
-					if (!(t->cred->credtype & allowed_auth_types)) {
-						giterr_set(GITERR_NET, "credentials callback returned an invalid cred type");
-						return t->parse_error = PARSE_ERROR_GENERIC;
-					}
-
-					/* Successfully acquired a credential. */
-					t->parse_error = PARSE_ERROR_REPLAY;
-					return 0;
-				}
-			}
-		}
-
-		if (no_callback) {
-			giterr_set(GITERR_NET, "authentication required but no callback set");
-			return t->parse_error = PARSE_ERROR_GENERIC;
-		}
-	}
-
-	/* Check for a redirect.
-	 * Right now we only permit a redirect to the same hostname. */
-	if ((parser->status_code == 301 ||
-	     parser->status_code == 302 ||
-	     (parser->status_code == 303 && get_verb == s->verb) ||
-	     parser->status_code == 307) &&
-	    t->location) {
-
-		if (s->redirect_count >= 7) {
-			giterr_set(GITERR_NET, "Too many redirects");
-			return t->parse_error = PARSE_ERROR_GENERIC;
-		}
-
-		if (gitno_connection_data_from_url(&t->connection_data, t->location, s->service_url) < 0)
-			return t->parse_error = PARSE_ERROR_GENERIC;
-
-		/* Set the redirect URL on the stream. This is a transfer of
-		 * ownership of the memory. */
-		if (s->redirect_url)
-			git__free(s->redirect_url);
-
-		s->redirect_url = t->location;
-		t->location = NULL;
-
-		t->connected = 0;
-		s->redirect_count++;
-
-		t->parse_error = PARSE_ERROR_REPLAY;
-		return 0;
-	}
-
-	/* Check for a 200 HTTP status code. */
-	if (parser->status_code != 200) {
-		giterr_set(GITERR_NET,
-			"Unexpected HTTP status code: %d",
-			parser->status_code);
-		return t->parse_error = PARSE_ERROR_GENERIC;
-	}
-
-	/* The response must contain a Content-Type header. */
-	if (!t->content_type) {
-		giterr_set(GITERR_NET, "No Content-Type header in response");
-		return t->parse_error = PARSE_ERROR_GENERIC;
-	}
-
-	/* The Content-Type header must match our expectation. */
-	if (get_verb == s->verb)
-		git_buf_printf(&buf,
-			"application/x-git-%s-advertisement",
-			ctx->s->service);
-	else
-		git_buf_printf(&buf,
-			"application/x-git-%s-result",
-			ctx->s->service);
-
-	if (git_buf_oom(&buf))
-		return t->parse_error = PARSE_ERROR_GENERIC;
-
-	if (strcmp(t->content_type, git_buf_cstr(&buf))) {
-		git_buf_free(&buf);
-		giterr_set(GITERR_NET,
-			"Invalid Content-Type: %s",
-			t->content_type);
-		return t->parse_error = PARSE_ERROR_GENERIC;
-	}
-
-	git_buf_free(&buf);
-
-	return 0;
-}
-
-static int on_message_complete(http_parser *parser)
-{
-	parser_context *ctx = (parser_context *) parser->data;
-	http_subtransport *t = ctx->t;
-
-	t->parse_finished = 1;
-
-	return 0;
-}
-
-static int on_body_fill_buffer(http_parser *parser, const char *str, size_t len)
-{
-	parser_context *ctx = (parser_context *) parser->data;
-	http_subtransport *t = ctx->t;
-
-	/* If our goal is to replay the request (either an auth failure or
-	 * a redirect) then don't bother buffering since we're ignoring the
-	 * content anyway.
-	 */
-	if (t->parse_error == PARSE_ERROR_REPLAY)
-		return 0;
-
-	if (ctx->buf_size < len) {
-		giterr_set(GITERR_NET, "Can't fit data in the buffer");
-		return t->parse_error = PARSE_ERROR_GENERIC;
-	}
-
-	memcpy(ctx->buffer, str, len);
-	*(ctx->bytes_read) += len;
-	ctx->buffer += len;
-	ctx->buf_size -= len;
-
-	return 0;
-}
-
-static void clear_parser_state(http_subtransport *t)
-{
-	http_parser_init(&t->parser, HTTP_RESPONSE);
-	gitno_buffer_setup_fromstream(t->io,
-		&t->parse_buffer,
-		t->parse_buffer_data,
-		sizeof(t->parse_buffer_data));
-
-	t->last_cb = NONE;
-	t->parse_error = 0;
-	t->parse_finished = 0;
-
-	git_buf_free(&t->parse_header_name);
-	git_buf_init(&t->parse_header_name, 0);
-
-	git_buf_free(&t->parse_header_value);
-	git_buf_init(&t->parse_header_value, 0);
-
-	git__free(t->content_type);
-	t->content_type = NULL;
-
-	git__free(t->location);
-	t->location = NULL;
-
-	git_vector_free_deep(&t->www_authenticate);
-}
-
-static int write_chunk(git_stream *io, const char *buffer, size_t len)
-{
-	git_buf buf = GIT_BUF_INIT;
-
-	/* Chunk header */
-	git_buf_printf(&buf, "%" PRIxZ "\r\n", len);
-
-	if (git_buf_oom(&buf))
-		return -1;
-
-	if (git_stream_write(io, buf.ptr, buf.size, 0) < 0) {
-		git_buf_free(&buf);
-		return -1;
-	}
-
-	git_buf_free(&buf);
-
-	/* Chunk body */
-	if (len > 0 && git_stream_write(io, buffer, len, 0) < 0)
-		return -1;
-
-	/* Chunk footer */
-	if (git_stream_write(io, "\r\n", 2, 0) < 0)
-		return -1;
-
-	return 0;
-}
-
-static int http_connect(http_subtransport *t)
-{
-	int error;
-	char *proxy_url;
-
-	if (t->connected &&
-		http_should_keep_alive(&t->parser) &&
-		t->parse_finished)
-		return 0;
-
-	if (t->io) {
-		git_stream_close(t->io);
-		git_stream_free(t->io);
-		t->io = NULL;
-	}
-
-	if (t->connection_data.use_ssl) {
-		error = git_tls_stream_new(&t->io, t->connection_data.host, t->connection_data.port);
-	} else {
-#ifdef GIT_CURL
-		error = git_curl_stream_new(&t->io, t->connection_data.host, t->connection_data.port);
-#else
-		error = git_socket_stream_new(&t->io,  t->connection_data.host, t->connection_data.port);
-#endif
-	}
-
-	if (error < 0)
-		return error;
-
-	GITERR_CHECK_VERSION(t->io, GIT_STREAM_VERSION, "git_stream");
-
-	if (git_stream_supports_proxy(t->io) &&
-	    !git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &proxy_url)) {
-		error = git_stream_set_proxy(t->io, proxy_url);
-		git__free(proxy_url);
-
-		if (error < 0)
-			return error;
-	}
-
-	error = git_stream_connect(t->io);
-
-#if defined(GIT_OPENSSL) || defined(GIT_SECURE_TRANSPORT) || defined(GIT_CURL)
-	if ((!error || error == GIT_ECERTIFICATE) && t->owner->certificate_check_cb != NULL &&
-	    git_stream_is_encrypted(t->io)) {
-		git_cert *cert;
-		int is_valid;
-
-		if ((error = git_stream_certificate(&cert, t->io)) < 0)
-			return error;
-
-		giterr_clear();
-		is_valid = error != GIT_ECERTIFICATE;
-		error = t->owner->certificate_check_cb(cert, is_valid, t->connection_data.host, t->owner->message_cb_payload);
-
-		if (error < 0) {
-			if (!giterr_last())
-				giterr_set(GITERR_NET, "user cancelled certificate check");
-
-			return error;
-		}
-	}
-#endif
-	if (error < 0)
-		return error;
-
-	t->connected = 1;
-	return 0;
-}
-
-static int http_stream_read(
-	git_smart_subtransport_stream *stream,
-	char *buffer,
-	size_t buf_size,
-	size_t *bytes_read)
-{
-	http_stream *s = (http_stream *)stream;
-	http_subtransport *t = OWNING_SUBTRANSPORT(s);
-	parser_context ctx;
-	size_t bytes_parsed;
-
-replay:
-	*bytes_read = 0;
-
-	assert(t->connected);
-
-	if (!s->sent_request) {
-		git_buf request = GIT_BUF_INIT;
-
-		clear_parser_state(t);
-
-		if (gen_request(&request, s, 0) < 0)
-			return -1;
-
-		if (git_stream_write(t->io, request.ptr, request.size, 0) < 0) {
-			git_buf_free(&request);
-			return -1;
-		}
-
-		git_buf_free(&request);
-
-		s->sent_request = 1;
-	}
-
-	if (!s->received_response) {
-		if (s->chunked) {
-			assert(s->verb == post_verb);
-
-			/* Flush, if necessary */
-			if (s->chunk_buffer_len > 0 &&
-				write_chunk(t->io, s->chunk_buffer, s->chunk_buffer_len) < 0)
-				return -1;
-
-			s->chunk_buffer_len = 0;
-
-			/* Write the final chunk. */
-			if (git_stream_write(t->io, "0\r\n\r\n", 5, 0) < 0)
-				return -1;
-		}
-
-		s->received_response = 1;
-	}
-
-	while (!*bytes_read && !t->parse_finished) {
-		size_t data_offset;
-		int error;
-
-		/*
-		 * Make the parse_buffer think it's as full of data as
-		 * the buffer, so it won't try to recv more data than
-		 * we can put into it.
-		 *
-		 * data_offset is the actual data offset from which we
-		 * should tell the parser to start reading.
-		 */
-		if (buf_size >= t->parse_buffer.len) {
-			t->parse_buffer.offset = 0;
-		} else {
-			t->parse_buffer.offset = t->parse_buffer.len - buf_size;
-		}
-
-		data_offset = t->parse_buffer.offset;
-
-		if (gitno_recv(&t->parse_buffer) < 0)
-			return -1;
-
-		/* This call to http_parser_execute will result in invocations of the
-		 * on_* family of callbacks. The most interesting of these is
-		 * on_body_fill_buffer, which is called when data is ready to be copied
-		 * into the target buffer. We need to marshal the buffer, buf_size, and
-		 * bytes_read parameters to this callback. */
-		ctx.t = t;
-		ctx.s = s;
-		ctx.buffer = buffer;
-		ctx.buf_size = buf_size;
-		ctx.bytes_read = bytes_read;
-
-		/* Set the context, call the parser, then unset the context. */
-		t->parser.data = &ctx;
-
-		bytes_parsed = http_parser_execute(&t->parser,
-			&t->settings,
-			t->parse_buffer.data + data_offset,
-			t->parse_buffer.offset - data_offset);
-
-		t->parser.data = NULL;
-
-		/* If there was a handled authentication failure, then parse_error
-		 * will have signaled us that we should replay the request. */
-		if (PARSE_ERROR_REPLAY == t->parse_error) {
-			s->sent_request = 0;
-
-			if ((error = http_connect(t)) < 0)
-				return error;
-
-			goto replay;
-		}
-
-		if (t->parse_error == PARSE_ERROR_EXT) {
-			return t->error;
-		}
-
-		if (t->parse_error < 0)
-			return -1;
-
-		if (bytes_parsed != t->parse_buffer.offset - data_offset) {
-			giterr_set(GITERR_NET,
-				"HTTP parser error: %s",
-				http_errno_description((enum http_errno)t->parser.http_errno));
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-static int http_stream_write_chunked(
-	git_smart_subtransport_stream *stream,
-	const char *buffer,
-	size_t len)
-{
-	http_stream *s = (http_stream *)stream;
-	http_subtransport *t = OWNING_SUBTRANSPORT(s);
-
-	assert(t->connected);
-
-	/* Send the request, if necessary */
-	if (!s->sent_request) {
-		git_buf request = GIT_BUF_INIT;
-
-		clear_parser_state(t);
-
-		if (gen_request(&request, s, 0) < 0)
-			return -1;
-
-		if (git_stream_write(t->io, request.ptr, request.size, 0) < 0) {
-			git_buf_free(&request);
-			return -1;
-		}
-
-		git_buf_free(&request);
-
-		s->sent_request = 1;
-	}
-
-	if (len > CHUNK_SIZE) {
-		/* Flush, if necessary */
-		if (s->chunk_buffer_len > 0) {
-			if (write_chunk(t->io, s->chunk_buffer, s->chunk_buffer_len) < 0)
-				return -1;
-
-			s->chunk_buffer_len = 0;
-		}
-
-		/* Write chunk directly */
-		if (write_chunk(t->io, buffer, len) < 0)
-			return -1;
-	}
-	else {
-		/* Append as much to the buffer as we can */
-		int count = min(CHUNK_SIZE - s->chunk_buffer_len, len);
-
-		if (!s->chunk_buffer)
-			s->chunk_buffer = git__malloc(CHUNK_SIZE);
-
-		memcpy(s->chunk_buffer + s->chunk_buffer_len, buffer, count);
-		s->chunk_buffer_len += count;
-		buffer += count;
-		len -= count;
-
-		/* Is the buffer full? If so, then flush */
-		if (CHUNK_SIZE == s->chunk_buffer_len) {
-			if (write_chunk(t->io, s->chunk_buffer, s->chunk_buffer_len) < 0)
-				return -1;
-
-			s->chunk_buffer_len = 0;
-
-			if (len > 0) {
-				memcpy(s->chunk_buffer, buffer, len);
-				s->chunk_buffer_len = len;
-			}
-		}
-	}
-
-	return 0;
-}
-
-static int http_stream_write_single(
-	git_smart_subtransport_stream *stream,
-	const char *buffer,
-	size_t len)
-{
-	http_stream *s = (http_stream *)stream;
-	http_subtransport *t = OWNING_SUBTRANSPORT(s);
-	git_buf request = GIT_BUF_INIT;
-
-	assert(t->connected);
-
-	if (s->sent_request) {
-		giterr_set(GITERR_NET, "Subtransport configured for only one write");
-		return -1;
-	}
-
-	clear_parser_state(t);
-
-	if (gen_request(&request, s, len) < 0)
-		return -1;
-
-	if (git_stream_write(t->io, request.ptr, request.size, 0) < 0)
-		goto on_error;
-
-	if (len && git_stream_write(t->io, buffer, len, 0) < 0)
-		goto on_error;
-
-	git_buf_free(&request);
-	s->sent_request = 1;
-
-	return 0;
-
-on_error:
-	git_buf_free(&request);
-	return -1;
-}
-
-static void http_stream_free(git_smart_subtransport_stream *stream)
-{
-	http_stream *s = (http_stream *)stream;
-
-	if (s->chunk_buffer)
-		git__free(s->chunk_buffer);
-
-	if (s->redirect_url)
-		git__free(s->redirect_url);
-
-	git__free(s);
-}
-
-static int http_stream_alloc(http_subtransport *t,
-	git_smart_subtransport_stream **stream)
-{
-	http_stream *s;
-
-	if (!stream)
-		return -1;
-
-	s = git__calloc(sizeof(http_stream), 1);
-	GITERR_CHECK_ALLOC(s);
-
-	s->parent.subtransport = &t->parent;
-	s->parent.read = http_stream_read;
-	s->parent.write = http_stream_write_single;
-	s->parent.free = http_stream_free;
-
-	*stream = (git_smart_subtransport_stream *)s;
-	return 0;
-}
-
-static int http_uploadpack_ls(
-	http_subtransport *t,
-	git_smart_subtransport_stream **stream)
-{
-	http_stream *s;
-
-	if (http_stream_alloc(t, stream) < 0)
-		return -1;
-
-	s = (http_stream *)*stream;
-
-	s->service = upload_pack_service;
-	s->service_url = upload_pack_ls_service_url;
-	s->verb = get_verb;
-
-	return 0;
-}
-
-static int http_uploadpack(
-	http_subtransport *t,
-	git_smart_subtransport_stream **stream)
-{
-	http_stream *s;
-
-	if (http_stream_alloc(t, stream) < 0)
-		return -1;
-
-	s = (http_stream *)*stream;
-
-	s->service = upload_pack_service;
-	s->service_url = upload_pack_service_url;
-	s->verb = post_verb;
-
-	return 0;
-}
-
-static int http_receivepack_ls(
-	http_subtransport *t,
-	git_smart_subtransport_stream **stream)
-{
-	http_stream *s;
-
-	if (http_stream_alloc(t, stream) < 0)
-		return -1;
-
-	s = (http_stream *)*stream;
-
-	s->service = receive_pack_service;
-	s->service_url = receive_pack_ls_service_url;
-	s->verb = get_verb;
-
-	return 0;
-}
-
-static int http_receivepack(
-	http_subtransport *t,
-	git_smart_subtransport_stream **stream)
-{
-	http_stream *s;
-
-	if (http_stream_alloc(t, stream) < 0)
-		return -1;
-
-	s = (http_stream *)*stream;
-
-	/* Use Transfer-Encoding: chunked for this request */
-	s->chunked = 1;
-	s->parent.write = http_stream_write_chunked;
-
-	s->service = receive_pack_service;
-	s->service_url = receive_pack_service_url;
-	s->verb = post_verb;
-
-	return 0;
-}
-
-static int http_action(
-	git_smart_subtransport_stream **stream,
-	git_smart_subtransport *subtransport,
-	const char *url,
-	git_smart_service_t action)
-{
-	http_subtransport *t = (http_subtransport *)subtransport;
-	int ret;
-
-	if (!stream)
-		return -1;
-
-	if ((!t->connection_data.host || !t->connection_data.port || !t->connection_data.path) &&
-		 (ret = gitno_connection_data_from_url(&t->connection_data, url, NULL)) < 0)
-		return ret;
-
-	if ((ret = http_connect(t)) < 0)
-		return ret;
-
-	switch (action) {
-	case GIT_SERVICE_UPLOADPACK_LS:
-		return http_uploadpack_ls(t, stream);
-
-	case GIT_SERVICE_UPLOADPACK:
-		return http_uploadpack(t, stream);
-
-	case GIT_SERVICE_RECEIVEPACK_LS:
-		return http_receivepack_ls(t, stream);
-
-	case GIT_SERVICE_RECEIVEPACK:
-		return http_receivepack(t, stream);
-	}
-
-	*stream = NULL;
-	return -1;
-}
-
-static int http_close(git_smart_subtransport *subtransport)
-{
-	http_subtransport *t = (http_subtransport *) subtransport;
-	git_http_auth_context *context;
-	size_t i;
-
-	clear_parser_state(t);
-
-	if (t->io) {
-		git_stream_close(t->io);
-		git_stream_free(t->io);
-		t->io = NULL;
-	}
-
-	if (t->cred) {
-		t->cred->free(t->cred);
-		t->cred = NULL;
-	}
-
-	if (t->url_cred) {
-		t->url_cred->free(t->url_cred);
-		t->url_cred = NULL;
-	}
-
-	git_vector_foreach(&t->auth_contexts, i, context) {
-		if (context->free)
-			context->free(context);
-	}
-
-	git_vector_clear(&t->auth_contexts);
-
-	gitno_connection_data_free_ptrs(&t->connection_data);
-	memset(&t->connection_data, 0x0, sizeof(gitno_connection_data));
-
-	return 0;
-}
-
-static void http_free(git_smart_subtransport *subtransport)
-{
-	http_subtransport *t = (http_subtransport *) subtransport;
-
-	http_close(subtransport);
-
-	git_vector_free(&t->auth_contexts);
-	git__free(t);
-}
-
-int git_smart_subtransport_http(git_smart_subtransport **out, git_transport *owner, void *param)
-{
-	http_subtransport *t;
-
-	GIT_UNUSED(param);
-
-	if (!out)
-		return -1;
-
-	t = git__calloc(sizeof(http_subtransport), 1);
-	GITERR_CHECK_ALLOC(t);
-
-	t->owner = (transport_smart *)owner;
-	t->parent.action = http_action;
-	t->parent.close = http_close;
-	t->parent.free = http_free;
-
-	t->settings.on_header_field = on_header_field;
-	t->settings.on_header_value = on_header_value;
-	t->settings.on_headers_complete = on_headers_complete;
-	t->settings.on_body = on_body_fill_buffer;
-	t->settings.on_message_complete = on_message_complete;
-
-	*out = (git_smart_subtransport *) t;
-	return 0;
-}
-
-#endif /* !GIT_WINHTTP */
diff -urpN libgit2-0.24.1.orig/src/transports/smart_pkt.c libgit2-0.24.1/src/transports/smart_pkt.c
--- libgit2-0.24.1.orig/src/transports/smart_pkt.c	2018-11-30 13:50:30.312789191 -0600
+++ libgit2-0.24.1/src/transports/smart_pkt.c	2018-12-03 15:55:59.292894819 -0600
@@ -382,7 +382,7 @@ static int32_t parse_len(const char *lin
 		}
 	}
 
-	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;
 
 	return len;
diff -urpN libgit2-0.24.1.orig/src/transports/winhttp.c libgit2-0.24.1/src/transports/winhttp.c
--- libgit2-0.24.1.orig/src/transports/winhttp.c	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/src/transports/winhttp.c	2018-12-03 15:55:59.292894819 -0600
@@ -603,7 +603,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 -urpN libgit2-0.24.1.orig/src/tree-cache.c libgit2-0.24.1/src/tree-cache.c
--- libgit2-0.24.1.orig/src/tree-cache.c	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/src/tree-cache.c	2018-12-03 15:52:12.747962464 -0600
@@ -90,7 +90,7 @@ static int read_tree_internal(git_tree_c
 		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;
@@ -99,7 +99,7 @@ static int read_tree_internal(git_tree_c
 		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 -urpN libgit2-0.24.1.orig/src/util.c libgit2-0.24.1/src/util.c
--- libgit2-0.24.1.orig/src/util.c	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/src/util.c	2018-12-10 11:59:37.398310363 -0600
@@ -64,7 +64,7 @@ int git_strarray_copy(git_strarray *tgt,
 	return 0;
 }
 
-int git__strtol64(int64_t *result, const char *nptr, const char **endptr, int base)
+int git__strntol64(int64_t *result, const char *nptr, size_t nptr_len, const char **endptr, int base)
 {
 	const char *p;
 	int64_t n, nn;
@@ -111,7 +111,7 @@ int git__strtol64(int64_t *result, const
 	/*
 	 * Non-empty sequence of digits
 	 */
-	for (;; p++,ndig++) {
+	for (; nptr_len > 0; p++,ndig++,nptr_len--) {
 		c = *p;
 		v = base;
 		if ('0'<=c && c<='9')
@@ -122,15 +122,25 @@ int git__strtol64(int64_t *result, const
 			v = c - 'A' + 10;
 		if (v >= base)
 			break;
-		nn = n*base + v;
-		if (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:
 	if (ndig == 0) {
-		giterr_set(GITERR_INVALID, "Failed to convert string to long. Not a number");
+		giterr_set(GITERR_INVALID, "failed to convert string to long: not a number");
 		return -1;
 	}
 
@@ -138,30 +148,34 @@ Return:
 		*endptr = p;
 
 	if (ovfl) {
-		giterr_set(GITERR_INVALID, "Failed to convert string to long. Overflow error");
+		giterr_set(GITERR_INVALID, "failed to convert string to long: overflow error");
 		return -1;
 	}
 
-	*result = neg ? -n : n;
+	*result = n;
 	return 0;
 }
 
-int git__strtol32(int32_t *result, const char *nptr, const char **endptr, int 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__strtol64(&tmp_long, nptr, 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;
 }
@@ -238,35 +252,47 @@ void git__strtolower(char *str)
 	git__strntolower(str, strlen(str));
 }
 
-int git__prefixcmp(const char *str, const char *prefix)
+GIT_INLINE(int) prefixcmp(const char *str, size_t str_n, const char *prefix, bool icase)
 {
-	for (;;) {
-		unsigned char p = *(prefix++), s;
+	int s, p;
+
+	while (str_n--) {
+		s = (unsigned char)*str++;
+		p = (unsigned char)*prefix++;
+
+		if (icase) {
+			s = git__tolower(s);
+			p = git__tolower(p);
+		}
+
 		if (!p)
 			return 0;
-		if ((s = *(str++)) != p)
+
+		if (s != p)
 			return s - p;
 	}
+
+	return (0 - *prefix);
 }
 
-int git__prefixcmp_icase(const char *str, const char *prefix)
+int git__prefixcmp(const char *str, const char *prefix)
 {
-	return strncasecmp(str, prefix, strlen(prefix));
+	return prefixcmp(str, SIZE_MAX, prefix, false);
 }
 
-int git__prefixncmp_icase(const char *str, size_t str_n, const char *prefix)
+int git__prefixncmp(const char *str, size_t str_n, const char *prefix)
 {
-	int s, p;
-
-	while(str_n--) {
-		s = (unsigned char)git__tolower(*str++);
-		p = (unsigned char)git__tolower(*prefix++);
+	return prefixcmp(str, str_n, prefix, false);
+}
 
-		if (s != p)
-			return s - p;
-	}
+int git__prefixcmp_icase(const char *str, const char *prefix)
+{
+	return prefixcmp(str, SIZE_MAX, prefix, true);
+}
 
-	return (0 - *prefix);
+int git__prefixncmp_icase(const char *str, size_t str_n, const char *prefix)
+{
+	return prefixcmp(str, str_n, prefix, true);
 }
 
 int git__suffixcmp(const char *str, const char *suffix)
@@ -319,6 +345,47 @@ char *git__strsep(char **end, const char
 	}
 
 	return NULL;
+}
+
+/*
+ * Adapted Not So Naive algorithm from http://www-igm.univ-mlv.fr/~lecroq/string/
+ */
+const void * git__memmem(const void *haystack, size_t haystacklen,
+			 const void *needle, size_t needlelen)
+{
+	const char *h, *n;
+	size_t j, k, l;
+
+	if (needlelen > haystacklen || !haystacklen || !needlelen)
+		return NULL;
+
+	h = (const char *) haystack,
+	n = (const char *) needle;
+
+	if (needlelen == 1)
+		return memchr(haystack, *n, haystacklen);
+
+	if (n[0] == n[1]) {
+		k = 2;
+		l = 1;
+	} else {
+		k = 1;
+		l = 2;
+	}
+
+	j = 0;
+	while (j <= haystacklen - needlelen) {
+		if (n[1] != h[j + 1]) {
+			j += k;
+		} else {
+			if (memcmp(n + 2, h + j + 2, needlelen - 2) == 0 &&
+			    n[0] == h[j])
+				return h + j;
+			j += l;
+		}
+	}
+
+	return NULL;
 }
 
 void git__hexdump(const char *buffer, size_t len)
diff -urpN libgit2-0.24.1.orig/src/util.h libgit2-0.24.1/src/util.h
--- libgit2-0.24.1.orig/src/util.h	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/src/util.h	2018-12-10 11:57:01.735357451 -0600
@@ -254,6 +254,7 @@ GIT_INLINE(void) git__free(void *ptr)
 
 extern int git__prefixcmp(const char *str, const char *prefix);
 extern int git__prefixcmp_icase(const char *str, const char *prefix);
+extern int git__prefixncmp(const char *str, size_t str_n, const char *prefix);
 extern int git__prefixncmp_icase(const char *str, size_t str_n, const char *prefix);
 extern int git__suffixcmp(const char *str, const char *suffix);
 
@@ -262,8 +263,9 @@ 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__strtol64(int64_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__strntol64(int64_t *n, const char *buff, size_t buff_len, const char **end_buf, int base);
+
 
 extern void git__hexdump(const char *buffer, size_t n);
 extern uint32_t git__hash(const void *key, int len, uint32_t seed);
@@ -312,6 +314,9 @@ GIT_INLINE(const void *) git__memrchr(co
 	return NULL;
 }
 
+extern const void * git__memmem(const void *haystack, size_t haystacklen,
+				const void *needle, size_t needlelen);
+
 typedef int (*git__tsort_cmp)(const void *a, const void *b);
 
 extern void git__tsort(void **dst, size_t size, git__tsort_cmp cmp);
diff -urpN libgit2-0.24.1.orig/tests/core/memmem.c libgit2-0.24.1/tests/core/memmem.c
--- libgit2-0.24.1.orig/tests/core/memmem.c	1969-12-31 18:00:00.000000000 -0600
+++ libgit2-0.24.1/tests/core/memmem.c	2018-12-03 16:29:09.245427048 -0600
@@ -0,0 +1,46 @@
+#include "clar_libgit2.h"
+
+static void assert_found(const char *haystack, const char *needle, size_t expected_pos)
+{
+	cl_assert_equal_p(git__memmem(haystack, haystack ? strlen(haystack) : 0,
+				      needle, needle ? strlen(needle) : 0),
+			  haystack + expected_pos);
+}
+
+static void assert_absent(const char *haystack, const char *needle)
+{
+	cl_assert_equal_p(git__memmem(haystack, haystack ? strlen(haystack) : 0,
+				      needle, needle ? strlen(needle) : 0),
+			  NULL);
+}
+
+void test_core_memmem__found(void)
+{
+	assert_found("a", "a", 0);
+	assert_found("ab", "a", 0);
+	assert_found("ba", "a", 1);
+	assert_found("aa", "a", 0);
+	assert_found("aab", "aa", 0);
+	assert_found("baa", "aa", 1);
+	assert_found("dabc", "abc", 1);
+	assert_found("abababc", "abc", 4);
+}
+
+void test_core_memmem__absent(void)
+{
+	assert_absent("a", "b");
+	assert_absent("a", "aa");
+	assert_absent("ba", "ab");
+	assert_absent("ba", "ab");
+	assert_absent("abc", "abcd");
+	assert_absent("abcabcabc", "bcac");
+}
+
+void test_core_memmem__edgecases(void)
+{
+	assert_absent(NULL, NULL);
+	assert_absent("a", NULL);
+	assert_absent(NULL, "a");
+	assert_absent("", "a");
+	assert_absent("a", "");
+}
diff -urpN libgit2-0.24.1.orig/tests/core/strtol.c libgit2-0.24.1/tests/core/strtol.c
--- libgit2-0.24.1.orig/tests/core/strtol.c	2016-04-11 17:18:17.000000000 -0500
+++ libgit2-0.24.1/tests/core/strtol.c	2018-12-10 11:47:08.871232203 -0600
@@ -1,37 +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);
+	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);
+}
openSUSE Build Service is sponsored by