static int extract_how_many(int *n, const char *spec, size_t *pos) { const char *end_ptr; int parsed, accumulated; char kind = spec[*pos]; assert(spec[*pos] == '^' || spec[*pos] == '~'); accumulated = 0; do { do { (*pos)++; accumulated++; } while (spec[(*pos)] == kind && kind == '~'); if (git__isdigit(spec[*pos])) { if (git__strtol32(&parsed, spec + *pos, &end_ptr, 10) < 0) return GIT_EINVALIDSPEC; accumulated += (parsed - 1); *pos = end_ptr - spec; } } while (spec[(*pos)] == kind && kind == '~'); *n = accumulated; return 0; }
static int winhttp_connect( winhttp_subtransport *t, const char *url) { wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")"; wchar_t *wide_host; int32_t port; const char *default_port = "80"; int error = -1; int default_timeout = TIMEOUT_INFINITE; int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT; /* Prepare port */ if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0) return -1; /* Prepare host */ if (git__utf8_to_16_alloc(&wide_host, t->connection_data.host) < 0) { giterr_set(GITERR_OS, "Unable to convert host to wide characters"); return -1; } /* Establish session */ t->session = WinHttpOpen( ua, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!t->session) { giterr_set(GITERR_OS, "Failed to init WinHTTP"); goto on_error; } if (!WinHttpSetTimeouts(t->session, default_timeout, default_connect_timeout, default_timeout, default_timeout)) { giterr_set(GITERR_OS, "Failed to set timeouts for WinHTTP"); goto on_error; } /* Establish connection */ t->connection = WinHttpConnect( t->session, wide_host, (INTERNET_PORT) port, 0); if (!t->connection) { giterr_set(GITERR_OS, "Failed to connect to host"); goto on_error; } error = 0; on_error: git__free(wide_host); return error; }
static int32_t parse_len(const char *line) { char num[PKT_LEN_SIZE + 1]; int i, k, error; int32_t len; const char *num_end; memcpy(num, line, PKT_LEN_SIZE); num[PKT_LEN_SIZE] = '\0'; for (i = 0; i < PKT_LEN_SIZE; ++i) { if (!isxdigit(num[i])) { /* Make sure there are no special characters before passing to error message */ for (k = 0; k < PKT_LEN_SIZE; ++k) { if(!isprint(num[k])) { num[k] = '.'; } } giterr_set(GITERR_NET, "invalid hex digit in length: '%s'", num); return -1; } } if ((error = git__strtol32(&len, num, &num_end, 16)) < 0) return error; return len; }
static int read_unmerged(git_index *index, const char *buffer, size_t size) { const char *endptr; size_t len; int i; git_vector_init(&index->unmerged, 16, unmerged_cmp); while (size) { git_index_entry_unmerged *lost; len = strlen(buffer) + 1; if (size <= len) return git__throw(GIT_ERROR, "Failed to read unmerged entries"); if ((lost = git__malloc(sizeof(git_index_entry_unmerged))) == NULL) return GIT_ENOMEM; if (git_vector_insert(&index->unmerged, lost) < GIT_SUCCESS) return git__throw(GIT_ERROR, "Failed to read unmerged entries"); lost->path = git__strdup(buffer); if (!lost->path) return GIT_ENOMEM; size -= len; buffer += len; for (i = 0; i < 3; i++) { long tmp; if (git__strtol32(&tmp, buffer, &endptr, 8) < GIT_SUCCESS || !endptr || endptr == buffer || *endptr || tmp > UINT_MAX) return GIT_ERROR; lost->mode[i] = tmp; len = (endptr + 1) - buffer; if (size <= len) return git__throw(GIT_ERROR, "Failed to read unmerged entries"); size -= len; buffer += len; } for (i = 0; i < 3; i++) { if (!lost->mode[i]) continue; if (size < 20) return git__throw(GIT_ERROR, "Failed to read unmerged entries"); git_oid_fromraw(&lost->oid[i], (unsigned char *) buffer); size -= 20; buffer += 20; } } return GIT_SUCCESS; }
static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buffer_end) { int error = GIT_SUCCESS; if (git_vector_init(&tree->entries, DEFAULT_TREE_SIZE, entry_sort_cmp) < GIT_SUCCESS) return GIT_ENOMEM; while (buffer < buffer_end) { git_tree_entry *entry; int tmp; entry = git__calloc(1, sizeof(git_tree_entry)); if (entry == NULL) { error = GIT_ENOMEM; break; } if (git_vector_insert(&tree->entries, entry) < GIT_SUCCESS) return GIT_ENOMEM; if (git__strtol32(&tmp, buffer, &buffer, 8) < GIT_SUCCESS || !buffer || !valid_attributes(tmp)) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse tree. Can't parse attributes"); entry->attr = tmp; if (*buffer++ != ' ') { error = git__throw(GIT_EOBJCORRUPTED, "Failed to parse tree. Object it corrupted"); break; } if (memchr(buffer, 0, buffer_end - buffer) == NULL) { error = git__throw(GIT_EOBJCORRUPTED, "Failed to parse tree. Object it corrupted"); break; } entry->filename = git__strdup(buffer); entry->filename_len = strlen(buffer); while (buffer < buffer_end && *buffer != 0) buffer++; buffer++; git_oid_fromraw(&entry->oid, (const unsigned char *)buffer); buffer += GIT_OID_RAWSZ; } return error == GIT_SUCCESS ? GIT_SUCCESS : git__rethrow(error, "Failed to parse buffer"); }
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) return -1; if (*end_ptr != '\0') return -1; *n = (int)content; return 0; }
static int parse_timezone_offset(const char *buffer, long *offset_out) { long offset, dec_offset; int mins, hours; const char *offset_start; const char *offset_end; //we are sure that *buffer == ' ' offset_start = buffer + 1; if (*offset_start == '\n') { *offset_out = 0; return GIT_SUCCESS; } if (offset_start[0] != '-' && offset_start[0] != '+') return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. It doesn't start with '+' or '-'"); if (offset_start[1] < '0' || offset_start[1] > '9') return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset."); if (git__strtol32(&dec_offset, offset_start + 1, &offset_end, 10) < GIT_SUCCESS) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. It isn't a number"); if (offset_end - offset_start != 5) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. Invalid length"); if (dec_offset > 1400) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. Value too large"); hours = dec_offset / 100; mins = dec_offset % 100; if (hours > 14) // see http://www.worldtimezone.com/faq.html return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. Hour value too large"); if (mins > 59) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse TZ offset. Minute value too large"); offset = (hours * 60) + mins; if (offset_start[0] == '-') offset *= -1; *offset_out = offset; return GIT_SUCCESS; }
int git_curl_stream_new(git_stream **out, const char *host, const char *port) { curl_stream *st; CURL *handle; int iport = 0, error; st = git__calloc(1, sizeof(curl_stream)); GITERR_CHECK_ALLOC(st); handle = curl_easy_init(); if (handle == NULL) { giterr_set(GITERR_NET, "failed to create curl handle"); git__free(st); return -1; } if ((error = git__strtol32(&iport, port, NULL, 10)) < 0) { git__free(st); return error; } curl_easy_setopt(handle, CURLOPT_URL, host); curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, st->curl_error); curl_easy_setopt(handle, CURLOPT_PORT, iport); curl_easy_setopt(handle, CURLOPT_CONNECT_ONLY, 1); curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 1); curl_easy_setopt(handle, CURLOPT_CERTINFO, 1); curl_easy_setopt(handle, CURLOPT_HTTPPROXYTUNNEL, 1); curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); /* curl_easy_setopt(handle, CURLOPT_VERBOSE, 1); */ st->parent.version = GIT_STREAM_VERSION; st->parent.encrypted = 0; /* we don't encrypt ourselves */ st->parent.proxy_support = 1; st->parent.connect = curls_connect; st->parent.certificate = curls_certificate; st->parent.set_proxy = curls_set_proxy; st->parent.read = curls_read; st->parent.write = curls_write; st->parent.close = curls_close; st->parent.free = curls_free; st->handle = handle; *out = (git_stream *) st; return 0; }
static int tree_parse_buffer(git_tree *tree, const char *buffer, const char *buffer_end) { int error = GIT_SUCCESS; if (git_vector_init(&tree->entries, DEFAULT_TREE_SIZE, entry_sort_cmp) < GIT_SUCCESS) return GIT_ENOMEM; while (buffer < buffer_end) { git_tree_entry *entry; entry = git__calloc(1, sizeof(git_tree_entry)); if (entry == NULL) { error = GIT_ENOMEM; break; } if (git_vector_insert(&tree->entries, entry) < GIT_SUCCESS) return GIT_ENOMEM; if (git__strtol32((long *)&entry->attr, buffer, &buffer, 8) < GIT_SUCCESS) return GIT_EOBJCORRUPTED; if (*buffer++ != ' ') { error = GIT_EOBJCORRUPTED; break; } if (memchr(buffer, 0, buffer_end - buffer) == NULL) { error = GIT_EOBJCORRUPTED; break; } entry->filename = git__strdup(buffer); entry->filename_len = strlen(buffer); while (buffer < buffer_end && *buffer != 0) buffer++; buffer++; git_oid_mkraw(&entry->oid, (const unsigned char *)buffer); buffer += GIT_OID_RAWSZ; } return error; }
GIT_INLINE(int) rebase_readint( size_t *out, git_buf *asc_out, git_buf *state_path, const char *filename) { int32_t num; const char *eol; int error = 0; 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) { giterr_set(GITERR_REBASE, "The file '%s' contains an invalid numeric value", filename); return -1; } *out = (size_t) num; return 0; }
static int winhttp_connect( winhttp_subtransport *t, const char *url) { wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")"; git_win32_path host; int32_t port; const char *default_port = "80"; /* Prepare port */ if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0) return -1; /* Prepare host */ git_win32_path_from_c(host, t->connection_data.host); /* Establish session */ t->session = WinHttpOpen( ua, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!t->session) { giterr_set(GITERR_OS, QT_TRANSLATE_NOOP("libgit2", "Failed to init WinHTTP")); return -1; } /* Establish connection */ t->connection = WinHttpConnect( t->session, host, (INTERNET_PORT) port, 0); if (!t->connection) { giterr_set(GITERR_OS, QT_TRANSLATE_NOOP("libgit2", "Failed to connect to host")); return -1; } return 0; }
void test_core_strtol__int32(void) { int32_t i; 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 int32_t parse_len(const char *line) { char num[PKT_LEN_SIZE + 1]; int i, error; int32_t len; const char *num_end; memcpy(num, line, PKT_LEN_SIZE); num[PKT_LEN_SIZE] = '\0'; for (i = 0; i < PKT_LEN_SIZE; ++i) { if (!isxdigit(num[i])) { giterr_set(GITERR_NET, "Found invalid hex digit in length"); return -1; } } if ((error = git__strtol32(&len, num, &num_end, 16)) < 0) return error; return len; }
static ssize_t parse_len(const char *line) { char num[PKT_LEN_SIZE + 1]; int i, error; long len; const char *num_end; memcpy(num, line, PKT_LEN_SIZE); num[PKT_LEN_SIZE] = '\0'; for (i = 0; i < PKT_LEN_SIZE; ++i) { if (!isxdigit(num[i])) return GIT_ENOTNUM; } error = git__strtol32(&len, num, &num_end, 16); if (error < GIT_SUCCESS) { return error; } return (unsigned int) len; }
static int read_tree_internal(git_index_tree **out, const char **buffer_in, const char *buffer_end, git_index_tree *parent) { git_index_tree *tree; const char *name_start, *buffer; long count; int error = GIT_SUCCESS; if ((tree = git__malloc(sizeof(git_index_tree))) == NULL) return GIT_ENOMEM; memset(tree, 0x0, sizeof(git_index_tree)); tree->parent = parent; buffer = name_start = *buffer_in; if ((buffer = memchr(buffer, '\0', buffer_end - buffer)) == NULL) { error = GIT_EOBJCORRUPTED; goto cleanup; } /* NUL-terminated tree name */ tree->name = git__strdup(name_start); if (tree->name == NULL) { error = GIT_ENOMEM; goto cleanup; } if (++buffer >= buffer_end) { error = GIT_EOBJCORRUPTED; goto cleanup; } /* Blank-terminated ASCII decimal number of entries in this tree */ if (git__strtol32(&count, buffer, &buffer, 10) < GIT_SUCCESS || count < -1) { error = GIT_EOBJCORRUPTED; goto cleanup; } /* Invalidated TREE. Free the tree but report success */ if (count == -1) { /* FIXME: return buffer_end or the end position for * this single tree entry */ *buffer_in = buffer_end; *out = NULL; free_tree(tree); /* Needs to be done manually */ return GIT_SUCCESS; } tree->entries = count; if (*buffer != ' ' || ++buffer >= buffer_end) { error = GIT_EOBJCORRUPTED; goto cleanup; } /* Number of children of the tree, newline-terminated */ if (git__strtol32(&count, buffer, &buffer, 10) < GIT_SUCCESS || count < 0) { error = GIT_EOBJCORRUPTED; goto cleanup; } tree->children_count = count; if (*buffer != '\n' || ++buffer >= buffer_end) { error = GIT_EOBJCORRUPTED; goto cleanup; } /* 160-bit SHA-1 for this tree and it's children */ if (buffer + GIT_OID_RAWSZ > buffer_end) { error = GIT_EOBJCORRUPTED; goto cleanup; } git_oid_fromraw(&tree->oid, (const unsigned char *)buffer); buffer += GIT_OID_RAWSZ; /* Parse children: */ if (tree->children_count > 0) { unsigned int i; int err; tree->children = git__malloc(tree->children_count * sizeof(git_index_tree *)); if (tree->children == NULL) goto cleanup; for (i = 0; i < tree->children_count; ++i) { err = read_tree_internal(&tree->children[i], &buffer, buffer_end, tree); if (err < GIT_SUCCESS) goto cleanup; } } *buffer_in = buffer; *out = tree; return GIT_SUCCESS; cleanup: free_tree(tree); return error; }
int git_signature__parse(git_signature *sig, const char **buffer_out, const char *buffer_end, const char *header, char ender) { const char *buffer = *buffer_out; const char *email_start, *email_end; memset(sig, 0, sizeof(git_signature)); if ((buffer_end = memchr(buffer, ender, buffer_end - buffer)) == NULL) return signature_error("no newline given"); if (header) { const size_t header_len = strlen(header); if (buffer + header_len >= buffer_end || memcmp(buffer, header, header_len) != 0) return signature_error("expected prefix doesn't match actual"); buffer += header_len; } email_start = git__memrchr(buffer, '<', buffer_end - buffer); email_end = git__memrchr(buffer, '>', buffer_end - buffer); if (!email_start || !email_end || email_end <= email_start) return signature_error("malformed e-mail"); email_start += 1; sig->name = extract_trimmed(buffer, email_start - buffer - 1); sig->email = extract_trimmed(email_start, email_end - email_start); /* Do we even have a time at the end of the signature? */ if (email_end + 2 < buffer_end) { const char *time_start = email_end + 2; const char *time_end; if (git__strtol64(&sig->when.time, time_start, &time_end, 10) < 0) return signature_error("invalid Unix timestamp"); /* do we have a timezone? */ if (time_end + 1 < buffer_end) { int offset, hours, mins; const char *tz_start, *tz_end; 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 offset = 0; } hours = offset / 100; mins = offset % 100; /* * only store timezone if it's not overflowing; * see http://www.worldtimezone.com/faq.html */ if (hours < 14 && mins < 59) { sig->when.offset = (hours * 60) + mins; if (tz_start[0] == '-') sig->when.offset = -sig->when.offset; } } } *buffer_out = buffer_end + 1; return 0; }
static int winhttp_connect( winhttp_subtransport *t) { wchar_t *wide_host; int32_t port; wchar_t *wide_ua; git_buf ua = GIT_BUF_INIT; int error = -1; int default_timeout = TIMEOUT_INFINITE; int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT; t->session = NULL; t->connection = NULL; /* Prepare port */ if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0) return -1; /* Prepare host */ if (git__utf8_to_16_alloc(&wide_host, t->connection_data.host) < 0) { giterr_set(GITERR_OS, "unable to convert host to wide characters"); return -1; } if ((error = user_agent(&ua)) < 0) { git__free(wide_host); return error; } if (git__utf8_to_16_alloc(&wide_ua, git_buf_cstr(&ua)) < 0) { giterr_set(GITERR_OS, "unable to convert host to wide characters"); git__free(wide_host); git_buf_free(&ua); return -1; } git_buf_free(&ua); /* Establish session */ t->session = WinHttpOpen( wide_ua, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!t->session) { giterr_set(GITERR_OS, "failed to init WinHTTP"); goto on_error; } if (!WinHttpSetTimeouts(t->session, default_timeout, default_connect_timeout, default_timeout, default_timeout)) { giterr_set(GITERR_OS, "failed to set timeouts for WinHTTP"); goto on_error; } /* Establish connection */ t->connection = WinHttpConnect( t->session, wide_host, (INTERNET_PORT) port, 0); if (!t->connection) { giterr_set(GITERR_OS, "failed to connect to host"); goto on_error; } if (WinHttpSetStatusCallback(t->connection, winhttp_status, WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, 0) == WINHTTP_INVALID_STATUS_CALLBACK) { giterr_set(GITERR_OS, "failed to set status callback"); goto on_error; } error = 0; on_error: if (error < 0) winhttp_close_connection(t); git__free(wide_host); git__free(wide_ua); return error; }
static int commit_quick_parse(git_revwalk *walk, git_commit_list_node *commit, git_rawobj *raw) { const size_t parent_len = strlen("parent ") + GIT_OID_HEXSZ + 1; unsigned char *buffer = raw->data; unsigned char *buffer_end = buffer + raw->len; unsigned char *parents_start, *committer_start; int i, parents = 0; int commit_time; buffer += strlen("tree ") + GIT_OID_HEXSZ + 1; parents_start = buffer; while (buffer + parent_len < buffer_end && memcmp(buffer, "parent ", strlen("parent ")) == 0) { parents++; buffer += parent_len; } commit->parents = alloc_parents(walk, commit, parents); GITERR_CHECK_ALLOC(commit->parents); buffer = parents_start; for (i = 0; i < parents; ++i) { git_oid oid; if (git_oid_fromstr(&oid, (char *)buffer + strlen("parent ")) < 0) return -1; commit->parents[i] = git_revwalk__commit_lookup(walk, &oid); if (commit->parents[i] == NULL) return -1; buffer += parent_len; } commit->out_degree = (unsigned short)parents; if ((committer_start = buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL) return commit_error(commit, "object is corrupted"); buffer++; if ((buffer = memchr(buffer, '\n', buffer_end - buffer)) == NULL) return commit_error(commit, "object is corrupted"); /* Skip trailing spaces */ while (buffer > committer_start && git__isspace(*buffer)) buffer--; /* Seek for the begining of the pack of digits */ while (buffer > committer_start && git__isdigit(*buffer)) buffer--; /* Skip potential timezone offset */ if ((buffer > committer_start) && (*buffer == '+' || *buffer == '-')) { buffer--; while (buffer > committer_start && git__isspace(*buffer)) buffer--; while (buffer > committer_start && git__isdigit(*buffer)) buffer--; } if ((buffer == committer_start) || (git__strtol32(&commit_time, (char *)(buffer + 1), NULL, 10) < 0)) return commit_error(commit, "cannot parse commit time"); commit->time = (time_t)commit_time; commit->parsed = 1; return 0; }
int git_signature__parse(git_signature *sig, const char **buffer_out, const char *buffer_end, const char *header) { const size_t header_len = strlen(header); int name_length, email_length; const char *buffer = *buffer_out; const char *line_end, *name_end, *email_end; long offset = 0, time; memset(sig, 0x0, sizeof(git_signature)); line_end = memchr(buffer, '\n', buffer_end - buffer); if (!line_end) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. No newline found");; if (buffer + (header_len + 1) > line_end) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Signature too short"); if (memcmp(buffer, header, header_len) != 0) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Expected prefix '%s' doesn't match actual", header); buffer += header_len; /* Parse name */ if ((name_end = strstr(buffer, " <")) == NULL) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Can't find e-mail start"); name_length = name_end - buffer; if (name_length <= 0) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Missing tagger name"); sig->name = git__malloc(name_length + 1); if (sig->name == NULL) return GIT_ENOMEM; memcpy(sig->name, buffer, name_length); sig->name[name_length] = 0; buffer = name_end + 2; if (buffer >= line_end) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Ended unexpectedly"); /* Parse email */ if ((email_end = strstr(buffer, "> ")) == NULL) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Can't find e-mail end"); email_length = email_end - buffer; sig->email = git__malloc(email_length + 1); if (sig->name == NULL) return GIT_ENOMEM; memcpy(sig->email, buffer, email_length); sig->email[email_length] = 0; buffer = email_end + 2; if (buffer >= line_end) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Ended unexpectedly"); /* verify email */ if (strpbrk(sig->email, "><\n ") != NULL) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Malformed e-mail"); if (git__strtol32(&time, buffer, &buffer, 10) < GIT_SUCCESS) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Timestamp isn't a number"); sig->when.time = (time_t)time; if (parse_timezone_offset(buffer, &offset) < GIT_SUCCESS) return git__throw(GIT_EOBJCORRUPTED, "Failed to parse signature. Could not parse timezone offset"); sig->when.offset = offset; *buffer_out = (line_end + 1); return GIT_SUCCESS; }
static int winhttp_connect( winhttp_subtransport *t) { wchar_t *wide_host; int32_t port; wchar_t *wide_ua; git_buf ua = GIT_BUF_INIT; int error = -1; int default_timeout = TIMEOUT_INFINITE; int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT; DWORD protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2; t->session = NULL; t->connection = NULL; /* Prepare port */ if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0) return -1; /* Prepare host */ if (git__utf8_to_16_alloc(&wide_host, t->connection_data.host) < 0) { giterr_set(GITERR_OS, "unable to convert host to wide characters"); return -1; } if ((error = git_http__user_agent(&ua)) < 0) { git__free(wide_host); return error; } if (git__utf8_to_16_alloc(&wide_ua, git_buf_cstr(&ua)) < 0) { giterr_set(GITERR_OS, "unable to convert host to wide characters"); git__free(wide_host); git_buf_free(&ua); return -1; } git_buf_free(&ua); /* Establish session */ t->session = WinHttpOpen( wide_ua, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!t->session) { giterr_set(GITERR_OS, "failed to init WinHTTP"); goto on_error; } /* * Do a best-effort attempt to enable TLS 1.2 but allow this to * fail; if TLS 1.2 support is not available for some reason, * ignore the failure (it will keep the default protocols). */ WinHttpSetOption(t->session, WINHTTP_OPTION_SECURE_PROTOCOLS, &protocols, sizeof(protocols)); if (!WinHttpSetTimeouts(t->session, default_timeout, default_connect_timeout, default_timeout, default_timeout)) { giterr_set(GITERR_OS, "failed to set timeouts for WinHTTP"); goto on_error; } /* Establish connection */ t->connection = WinHttpConnect( t->session, wide_host, (INTERNET_PORT) port, 0); if (!t->connection) { giterr_set(GITERR_OS, "failed to connect to host"); goto on_error; } if (WinHttpSetStatusCallback(t->connection, winhttp_status, WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, 0) == WINHTTP_INVALID_STATUS_CALLBACK) { giterr_set(GITERR_OS, "failed to set status callback"); goto on_error; } error = 0; on_error: if (error < 0) winhttp_close_connection(t); git__free(wide_host); git__free(wide_ua); return error; }
static int read_tree_internal(git_tree_cache **out, const char **buffer_in, const char *buffer_end, git_tree_cache *parent) { git_tree_cache *tree = NULL; const char *name_start, *buffer; int count; size_t name_len; buffer = name_start = *buffer_in; if ((buffer = memchr(buffer, '\0', buffer_end - buffer)) == NULL) goto corrupted; if (++buffer >= buffer_end) goto corrupted; name_len = strlen(name_start); tree = git__malloc(sizeof(git_tree_cache) + name_len + 1); GITERR_CHECK_ALLOC(tree); memset(tree, 0x0, sizeof(git_tree_cache)); tree->parent = parent; /* NUL-terminated tree name */ memcpy(tree->name, name_start, name_len); tree->name[name_len] = '\0'; /* Blank-terminated ASCII decimal number of entries in this tree */ if (git__strtol32(&count, buffer, &buffer, 10) < 0) goto corrupted; tree->entries = count; if (*buffer != ' ' || ++buffer >= buffer_end) goto corrupted; /* Number of children of the tree, newline-terminated */ if (git__strtol32(&count, buffer, &buffer, 10) < 0 || count < 0) goto corrupted; tree->children_count = count; if (*buffer != '\n' || ++buffer > buffer_end) goto corrupted; /* The SHA1 is only there if it's not invalidated */ if (tree->entries >= 0) { /* 160-bit SHA-1 for this tree and it's children */ if (buffer + GIT_OID_RAWSZ > buffer_end) goto corrupted; git_oid_fromraw(&tree->oid, (const unsigned char *)buffer); buffer += GIT_OID_RAWSZ; } /* Parse children: */ if (tree->children_count > 0) { unsigned int i; tree->children = git__malloc(tree->children_count * sizeof(git_tree_cache *)); GITERR_CHECK_ALLOC(tree->children); memset(tree->children, 0x0, tree->children_count * sizeof(git_tree_cache *)); for (i = 0; i < tree->children_count; ++i) { if (read_tree_internal(&tree->children[i], &buffer, buffer_end, tree) < 0) goto corrupted; } } *buffer_in = buffer; *out = tree; return 0; corrupted: git_tree_cache_free(tree); giterr_set(GITERR_INDEX, "Corrupted TREE extension in index"); return -1; }