Esempio n. 1
0
void test_object_raw_hash__hash_buffer_in_single_call(void)
{
    git_oid id1, id2;

    cl_git_pass(git_oid_fromstr(&id1, hello_id));
    git_hash_buf(&id2, hello_text, strlen(hello_text));
    cl_assert(git_oid_cmp(&id1, &id2) == 0);
}
Esempio n. 2
0
File: index.c Progetto: hef/libgit2
int git_index__parse(git_index *index, const char *buffer, size_t buffer_size)
{
	unsigned int i;
	struct index_header header;
	git_oid checksum_calculated, checksum_expected;

#define seek_forward(_increase) { \
	if (_increase >= buffer_size) \
		return GIT_EOBJCORRUPTED; \
	buffer += _increase; \
	buffer_size -= _increase;\
}

	if (buffer_size < INDEX_HEADER_SIZE + INDEX_FOOTER_SIZE)
		return GIT_EOBJCORRUPTED;

	/* Precalculate the SHA1 of the files's contents -- we'll match it to
	 * the provided SHA1 in the footer */
	git_hash_buf(&checksum_calculated, (const void *)buffer, buffer_size - INDEX_FOOTER_SIZE);

	/* Parse header */
	if (read_header(&header, buffer) < 0)
		return GIT_EOBJCORRUPTED;

	seek_forward(INDEX_HEADER_SIZE);

	index->entry_count = header.entry_count;

	/* If there is already a entires array, reuse it if it can hold all the
	 * entries. If not, free and reallocate */
	if (index->entry_count > index->entries_size) {
		free(index->entries);
		index->entries_size = (uint32_t)(index->entry_count * 1.3f);
		index->entries = git__malloc(index->entries_size * sizeof(git_index_entry));
	}

	/* Parse all the entries */
	for (i = 0; i < index->entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
		size_t entry_size;
		entry_size = read_entry(&index->entries[i], buffer, buffer_size);

		/* 0 bytes read means an object corruption */
		if (entry_size == 0)
			return GIT_EOBJCORRUPTED;

		seek_forward(entry_size);
	}

	if (i != index->entry_count)
		return GIT_EOBJCORRUPTED;

	/* There's still space for some extensions! */
	while (buffer_size > INDEX_FOOTER_SIZE) {
		size_t extension_size;

		extension_size = read_extension(index, buffer, buffer_size);

		/* see if we have read any bytes from the extension */
		if (extension_size == 0)
			return GIT_EOBJCORRUPTED;

		seek_forward(extension_size);
	}

	if (buffer_size != INDEX_FOOTER_SIZE)
		return GIT_EOBJCORRUPTED;

	/* 160-bit SHA-1 over the content of the index file before this checksum. */
	git_oid_mkraw(&checksum_expected, (const unsigned char *)buffer);

	if (git_oid_cmp(&checksum_calculated, &checksum_expected) != 0)
		return GIT_EOBJCORRUPTED;

#undef seek_forward

	return 0;
}
Esempio n. 3
0
int git_futils_readbuffer_updated(
	git_buf *out, const char *path, git_oid *checksum, int *updated)
{
	int error;
	git_file fd;
	struct stat st;
	git_buf buf = GIT_BUF_INIT;
	git_oid checksum_new;

	assert(out && path && *path);

	if (updated != NULL)
		*updated = 0;

	if (p_stat(path, &st) < 0)
		return git_path_set_error(errno, path, "stat");


	if (S_ISDIR(st.st_mode)) {
		giterr_set(GITERR_INVALID, "requested file is a directory");
		return GIT_ENOTFOUND;
	}

	if (!git__is_sizet(st.st_size+1)) {
		giterr_set(GITERR_OS, "invalid regular file stat for '%s'", path);
		return -1;
	}

	if ((fd = git_futils_open_ro(path)) < 0)
		return fd;

	if (git_futils_readbuffer_fd(&buf, fd, (size_t)st.st_size) < 0) {
		p_close(fd);
		return -1;
	}

	p_close(fd);

	if (checksum) {
		if ((error = git_hash_buf(&checksum_new, buf.ptr, buf.size)) < 0) {
			git_buf_free(&buf);
			return error;
		}

		/*
		 * If we were given a checksum, we only want to use it if it's different
		 */
		if (!git_oid__cmp(checksum, &checksum_new)) {
			git_buf_free(&buf);
			if (updated)
				*updated = 0;

			return 0;
		}

		git_oid_cpy(checksum, &checksum_new);
	}

	/*
	 * If we're here, the file did change, or the user didn't have an old version
	 */
	if (updated != NULL)
		*updated = 1;

	git_buf_swap(out, &buf);
	git_buf_free(&buf);

	return 0;
}
Esempio n. 4
0
void test_object_raw_short__oid_shortener_stresstest_git_oid_shorten(void)
{
#define MAX_OIDS 1000

	git_oid_shorten *os;
	char *oids[MAX_OIDS];
	char number_buffer[16];
	git_oid oid;
	size_t i, j;

	int min_len = 0, found_collision;

	os = git_oid_shorten_new(0);
	cl_assert(os != NULL);

	/*
	 * Insert in the shortener 1000 unique SHA1 ids
	 */
	for (i = 0; i < MAX_OIDS; ++i) {
		char *oid_text;

		sprintf(number_buffer, "%u", (unsigned int)i);
		git_hash_buf(&oid, number_buffer, strlen(number_buffer));

		oid_text = git__malloc(GIT_OID_HEXSZ + 1);
		git_oid_fmt(oid_text, &oid);
		oid_text[GIT_OID_HEXSZ] = 0;

		min_len = git_oid_shorten_add(os, oid_text);
		cl_assert(min_len >= 0);

		oids[i] = oid_text;
	}

	/*
	 * Compare the first `min_char - 1` characters of each
	 * SHA1 OID. If the minimizer worked, we should find at
	 * least one collision
	 */
	found_collision = 0;
	for (i = 0; i < MAX_OIDS; ++i) {
		for (j = 0; j < MAX_OIDS; ++j) {
			if (i != j && memcmp(oids[i], oids[j], min_len - 1) == 0)
				found_collision = 1;
		}
	}
	cl_assert(found_collision == 1);

	/*
	 * Compare the first `min_char` characters of each
	 * SHA1 OID. If the minimizer worked, every single preffix
	 * should be unique.
	 */
	found_collision = 0;
	for (i = 0; i < MAX_OIDS; ++i) {
		for (j = 0; j < MAX_OIDS; ++j) {
			if (i != j && memcmp(oids[i], oids[j], min_len) == 0)
				found_collision = 1;
		}
	}
	cl_assert(found_collision == 0);

	/* cleanup */
	for (i = 0; i < MAX_OIDS; ++i)
		git__free(oids[i]);

	git_oid_shorten_free(os);

#undef MAX_OIDS
}
Esempio n. 5
0
static int parse_index(git_index *index, const char *buffer, size_t buffer_size)
{
	unsigned int i;
	struct index_header header;
	git_oid checksum_calculated, checksum_expected;

#define seek_forward(_increase) { \
	if (_increase >= buffer_size) \
		return git__throw(GIT_EOBJCORRUPTED, "Failed to seek forward. Buffer size exceeded"); \
	buffer += _increase; \
	buffer_size -= _increase;\
}

	if (buffer_size < INDEX_HEADER_SIZE + INDEX_FOOTER_SIZE)
		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Buffer too small");

	/* Precalculate the SHA1 of the files's contents -- we'll match it to
	 * the provided SHA1 in the footer */
	git_hash_buf(&checksum_calculated, buffer, buffer_size - INDEX_FOOTER_SIZE);

	/* Parse header */
	if (read_header(&header, buffer) < GIT_SUCCESS)
		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Header is corrupted");

	seek_forward(INDEX_HEADER_SIZE);

	git_vector_clear(&index->entries);

	/* Parse all the entries */
	for (i = 0; i < header.entry_count && buffer_size > INDEX_FOOTER_SIZE; ++i) {
		size_t entry_size;
		git_index_entry *entry;

		entry = git__malloc(sizeof(git_index_entry));
		if (entry == NULL)
			return GIT_ENOMEM;

		entry_size = read_entry(entry, buffer, buffer_size);

		/* 0 bytes read means an object corruption */
		if (entry_size == 0)
			return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Entry size is zero");

		if (git_vector_insert(&index->entries, entry) < GIT_SUCCESS)
			return GIT_ENOMEM;

		seek_forward(entry_size);
	}

	if (i != header.entry_count)
		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Header entries changed while parsing");

	/* There's still space for some extensions! */
	while (buffer_size > INDEX_FOOTER_SIZE) {
		size_t extension_size;

		extension_size = read_extension(index, buffer, buffer_size);

		/* see if we have read any bytes from the extension */
		if (extension_size == 0)
			return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Extension size is zero");

		seek_forward(extension_size);
	}

	if (buffer_size != INDEX_FOOTER_SIZE)
		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Buffer size does not match index footer size");

	/* 160-bit SHA-1 over the content of the index file before this checksum. */
	git_oid_fromraw(&checksum_expected, (const unsigned char *)buffer);

	if (git_oid_cmp(&checksum_calculated, &checksum_expected) != 0)
		return git__throw(GIT_EOBJCORRUPTED, "Failed to parse index. Calculated checksum does not match expected checksum");

#undef seek_forward

	/* force sorting in the vector: the entries are
	 * assured to be sorted on the index */
	index->entries.sorted = 1;
	return GIT_SUCCESS;
}