|  | 
|  | 1 | +#define USE_THE_REPOSITORY_VARIABLE | 
|  | 2 | +#define DISABLE_SIGN_COMPARE_WARNINGS | 
|  | 3 | + | 
|  | 4 | +#include "git-compat-util.h" | 
|  | 5 | +#include "hash.h" | 
|  | 6 | +#include "hex.h" | 
|  | 7 | + | 
|  | 8 | +static const struct object_id empty_tree_oid = { | 
|  | 9 | +	.hash = { | 
|  | 10 | +		0x4b, 0x82, 0x5d, 0xc6, 0x42, 0xcb, 0x6e, 0xb9, 0xa0, 0x60, | 
|  | 11 | +		0xe5, 0x4b, 0xf8, 0xd6, 0x92, 0x88, 0xfb, 0xee, 0x49, 0x04 | 
|  | 12 | +	}, | 
|  | 13 | +	.algo = GIT_HASH_SHA1, | 
|  | 14 | +}; | 
|  | 15 | +static const struct object_id empty_blob_oid = { | 
|  | 16 | +	.hash = { | 
|  | 17 | +		0xe6, 0x9d, 0xe2, 0x9b, 0xb2, 0xd1, 0xd6, 0x43, 0x4b, 0x8b, | 
|  | 18 | +		0x29, 0xae, 0x77, 0x5a, 0xd8, 0xc2, 0xe4, 0x8c, 0x53, 0x91 | 
|  | 19 | +	}, | 
|  | 20 | +	.algo = GIT_HASH_SHA1, | 
|  | 21 | +}; | 
|  | 22 | +static const struct object_id null_oid_sha1 = { | 
|  | 23 | +	.hash = {0}, | 
|  | 24 | +	.algo = GIT_HASH_SHA1, | 
|  | 25 | +}; | 
|  | 26 | +static const struct object_id empty_tree_oid_sha256 = { | 
|  | 27 | +	.hash = { | 
|  | 28 | +		0x6e, 0xf1, 0x9b, 0x41, 0x22, 0x5c, 0x53, 0x69, 0xf1, 0xc1, | 
|  | 29 | +		0x04, 0xd4, 0x5d, 0x8d, 0x85, 0xef, 0xa9, 0xb0, 0x57, 0xb5, | 
|  | 30 | +		0x3b, 0x14, 0xb4, 0xb9, 0xb9, 0x39, 0xdd, 0x74, 0xde, 0xcc, | 
|  | 31 | +		0x53, 0x21 | 
|  | 32 | +	}, | 
|  | 33 | +	.algo = GIT_HASH_SHA256, | 
|  | 34 | +}; | 
|  | 35 | +static const struct object_id empty_blob_oid_sha256 = { | 
|  | 36 | +	.hash = { | 
|  | 37 | +		0x47, 0x3a, 0x0f, 0x4c, 0x3b, 0xe8, 0xa9, 0x36, 0x81, 0xa2, | 
|  | 38 | +		0x67, 0xe3, 0xb1, 0xe9, 0xa7, 0xdc, 0xda, 0x11, 0x85, 0x43, | 
|  | 39 | +		0x6f, 0xe1, 0x41, 0xf7, 0x74, 0x91, 0x20, 0xa3, 0x03, 0x72, | 
|  | 40 | +		0x18, 0x13 | 
|  | 41 | +	}, | 
|  | 42 | +	.algo = GIT_HASH_SHA256, | 
|  | 43 | +}; | 
|  | 44 | +static const struct object_id null_oid_sha256 = { | 
|  | 45 | +	.hash = {0}, | 
|  | 46 | +	.algo = GIT_HASH_SHA256, | 
|  | 47 | +}; | 
|  | 48 | + | 
|  | 49 | +static void git_hash_sha1_init(struct git_hash_ctx *ctx) | 
|  | 50 | +{ | 
|  | 51 | +	ctx->algop = &hash_algos[GIT_HASH_SHA1]; | 
|  | 52 | +	git_SHA1_Init(&ctx->state.sha1); | 
|  | 53 | +} | 
|  | 54 | + | 
|  | 55 | +static void git_hash_sha1_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src) | 
|  | 56 | +{ | 
|  | 57 | +	dst->algop = src->algop; | 
|  | 58 | +	git_SHA1_Clone(&dst->state.sha1, &src->state.sha1); | 
|  | 59 | +} | 
|  | 60 | + | 
|  | 61 | +static void git_hash_sha1_update(struct git_hash_ctx *ctx, const void *data, size_t len) | 
|  | 62 | +{ | 
|  | 63 | +	git_SHA1_Update(&ctx->state.sha1, data, len); | 
|  | 64 | +} | 
|  | 65 | + | 
|  | 66 | +static void git_hash_sha1_final(unsigned char *hash, struct git_hash_ctx *ctx) | 
|  | 67 | +{ | 
|  | 68 | +	git_SHA1_Final(hash, &ctx->state.sha1); | 
|  | 69 | +} | 
|  | 70 | + | 
|  | 71 | +static void git_hash_sha1_final_oid(struct object_id *oid, struct git_hash_ctx *ctx) | 
|  | 72 | +{ | 
|  | 73 | +	git_SHA1_Final(oid->hash, &ctx->state.sha1); | 
|  | 74 | +	memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ); | 
|  | 75 | +	oid->algo = GIT_HASH_SHA1; | 
|  | 76 | +} | 
|  | 77 | + | 
|  | 78 | +static void git_hash_sha1_init_unsafe(struct git_hash_ctx *ctx) | 
|  | 79 | +{ | 
|  | 80 | +	ctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA1]); | 
|  | 81 | +	git_SHA1_Init_unsafe(&ctx->state.sha1_unsafe); | 
|  | 82 | +} | 
|  | 83 | + | 
|  | 84 | +static void git_hash_sha1_clone_unsafe(struct git_hash_ctx *dst, const struct git_hash_ctx *src) | 
|  | 85 | +{ | 
|  | 86 | +	dst->algop = src->algop; | 
|  | 87 | +	git_SHA1_Clone_unsafe(&dst->state.sha1_unsafe, &src->state.sha1_unsafe); | 
|  | 88 | +} | 
|  | 89 | + | 
|  | 90 | +static void git_hash_sha1_update_unsafe(struct git_hash_ctx *ctx, const void *data, | 
|  | 91 | +				      size_t len) | 
|  | 92 | +{ | 
|  | 93 | +	git_SHA1_Update_unsafe(&ctx->state.sha1_unsafe, data, len); | 
|  | 94 | +} | 
|  | 95 | + | 
|  | 96 | +static void git_hash_sha1_final_unsafe(unsigned char *hash, struct git_hash_ctx *ctx) | 
|  | 97 | +{ | 
|  | 98 | +	git_SHA1_Final_unsafe(hash, &ctx->state.sha1_unsafe); | 
|  | 99 | +} | 
|  | 100 | + | 
|  | 101 | +static void git_hash_sha1_final_oid_unsafe(struct object_id *oid, struct git_hash_ctx *ctx) | 
|  | 102 | +{ | 
|  | 103 | +	git_SHA1_Final_unsafe(oid->hash, &ctx->state.sha1_unsafe); | 
|  | 104 | +	memset(oid->hash + GIT_SHA1_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA1_RAWSZ); | 
|  | 105 | +	oid->algo = GIT_HASH_SHA1; | 
|  | 106 | +} | 
|  | 107 | + | 
|  | 108 | +static void git_hash_sha256_init(struct git_hash_ctx *ctx) | 
|  | 109 | +{ | 
|  | 110 | +	ctx->algop = unsafe_hash_algo(&hash_algos[GIT_HASH_SHA256]); | 
|  | 111 | +	git_SHA256_Init(&ctx->state.sha256); | 
|  | 112 | +} | 
|  | 113 | + | 
|  | 114 | +static void git_hash_sha256_clone(struct git_hash_ctx *dst, const struct git_hash_ctx *src) | 
|  | 115 | +{ | 
|  | 116 | +	dst->algop = src->algop; | 
|  | 117 | +	git_SHA256_Clone(&dst->state.sha256, &src->state.sha256); | 
|  | 118 | +} | 
|  | 119 | + | 
|  | 120 | +static void git_hash_sha256_update(struct git_hash_ctx *ctx, const void *data, size_t len) | 
|  | 121 | +{ | 
|  | 122 | +	git_SHA256_Update(&ctx->state.sha256, data, len); | 
|  | 123 | +} | 
|  | 124 | + | 
|  | 125 | +static void git_hash_sha256_final(unsigned char *hash, struct git_hash_ctx *ctx) | 
|  | 126 | +{ | 
|  | 127 | +	git_SHA256_Final(hash, &ctx->state.sha256); | 
|  | 128 | +} | 
|  | 129 | + | 
|  | 130 | +static void git_hash_sha256_final_oid(struct object_id *oid, struct git_hash_ctx *ctx) | 
|  | 131 | +{ | 
|  | 132 | +	git_SHA256_Final(oid->hash, &ctx->state.sha256); | 
|  | 133 | +	/* | 
|  | 134 | +	 * This currently does nothing, so the compiler should optimize it out, | 
|  | 135 | +	 * but keep it in case we extend the hash size again. | 
|  | 136 | +	 */ | 
|  | 137 | +	memset(oid->hash + GIT_SHA256_RAWSZ, 0, GIT_MAX_RAWSZ - GIT_SHA256_RAWSZ); | 
|  | 138 | +	oid->algo = GIT_HASH_SHA256; | 
|  | 139 | +} | 
|  | 140 | + | 
|  | 141 | +static void git_hash_unknown_init(struct git_hash_ctx *ctx UNUSED) | 
|  | 142 | +{ | 
|  | 143 | +	BUG("trying to init unknown hash"); | 
|  | 144 | +} | 
|  | 145 | + | 
|  | 146 | +static void git_hash_unknown_clone(struct git_hash_ctx *dst UNUSED, | 
|  | 147 | +				   const struct git_hash_ctx *src UNUSED) | 
|  | 148 | +{ | 
|  | 149 | +	BUG("trying to clone unknown hash"); | 
|  | 150 | +} | 
|  | 151 | + | 
|  | 152 | +static void git_hash_unknown_update(struct git_hash_ctx *ctx UNUSED, | 
|  | 153 | +				    const void *data UNUSED, | 
|  | 154 | +				    size_t len UNUSED) | 
|  | 155 | +{ | 
|  | 156 | +	BUG("trying to update unknown hash"); | 
|  | 157 | +} | 
|  | 158 | + | 
|  | 159 | +static void git_hash_unknown_final(unsigned char *hash UNUSED, | 
|  | 160 | +				   struct git_hash_ctx *ctx UNUSED) | 
|  | 161 | +{ | 
|  | 162 | +	BUG("trying to finalize unknown hash"); | 
|  | 163 | +} | 
|  | 164 | + | 
|  | 165 | +static void git_hash_unknown_final_oid(struct object_id *oid UNUSED, | 
|  | 166 | +				       struct git_hash_ctx *ctx UNUSED) | 
|  | 167 | +{ | 
|  | 168 | +	BUG("trying to finalize unknown hash"); | 
|  | 169 | +} | 
|  | 170 | + | 
|  | 171 | +static const struct git_hash_algo sha1_unsafe_algo = { | 
|  | 172 | +	.name = "sha1", | 
|  | 173 | +	.format_id = GIT_SHA1_FORMAT_ID, | 
|  | 174 | +	.rawsz = GIT_SHA1_RAWSZ, | 
|  | 175 | +	.hexsz = GIT_SHA1_HEXSZ, | 
|  | 176 | +	.blksz = GIT_SHA1_BLKSZ, | 
|  | 177 | +	.init_fn = git_hash_sha1_init_unsafe, | 
|  | 178 | +	.clone_fn = git_hash_sha1_clone_unsafe, | 
|  | 179 | +	.update_fn = git_hash_sha1_update_unsafe, | 
|  | 180 | +	.final_fn = git_hash_sha1_final_unsafe, | 
|  | 181 | +	.final_oid_fn = git_hash_sha1_final_oid_unsafe, | 
|  | 182 | +	.empty_tree = &empty_tree_oid, | 
|  | 183 | +	.empty_blob = &empty_blob_oid, | 
|  | 184 | +	.null_oid = &null_oid_sha1, | 
|  | 185 | +}; | 
|  | 186 | + | 
|  | 187 | +const struct git_hash_algo hash_algos[GIT_HASH_NALGOS] = { | 
|  | 188 | +	{ | 
|  | 189 | +		.name = NULL, | 
|  | 190 | +		.format_id = 0x00000000, | 
|  | 191 | +		.rawsz = 0, | 
|  | 192 | +		.hexsz = 0, | 
|  | 193 | +		.blksz = 0, | 
|  | 194 | +		.init_fn = git_hash_unknown_init, | 
|  | 195 | +		.clone_fn = git_hash_unknown_clone, | 
|  | 196 | +		.update_fn = git_hash_unknown_update, | 
|  | 197 | +		.final_fn = git_hash_unknown_final, | 
|  | 198 | +		.final_oid_fn = git_hash_unknown_final_oid, | 
|  | 199 | +		.empty_tree = NULL, | 
|  | 200 | +		.empty_blob = NULL, | 
|  | 201 | +		.null_oid = NULL, | 
|  | 202 | +	}, | 
|  | 203 | +	{ | 
|  | 204 | +		.name = "sha1", | 
|  | 205 | +		.format_id = GIT_SHA1_FORMAT_ID, | 
|  | 206 | +		.rawsz = GIT_SHA1_RAWSZ, | 
|  | 207 | +		.hexsz = GIT_SHA1_HEXSZ, | 
|  | 208 | +		.blksz = GIT_SHA1_BLKSZ, | 
|  | 209 | +		.init_fn = git_hash_sha1_init, | 
|  | 210 | +		.clone_fn = git_hash_sha1_clone, | 
|  | 211 | +		.update_fn = git_hash_sha1_update, | 
|  | 212 | +		.final_fn = git_hash_sha1_final, | 
|  | 213 | +		.final_oid_fn = git_hash_sha1_final_oid, | 
|  | 214 | +		.unsafe = &sha1_unsafe_algo, | 
|  | 215 | +		.empty_tree = &empty_tree_oid, | 
|  | 216 | +		.empty_blob = &empty_blob_oid, | 
|  | 217 | +		.null_oid = &null_oid_sha1, | 
|  | 218 | +	}, | 
|  | 219 | +	{ | 
|  | 220 | +		.name = "sha256", | 
|  | 221 | +		.format_id = GIT_SHA256_FORMAT_ID, | 
|  | 222 | +		.rawsz = GIT_SHA256_RAWSZ, | 
|  | 223 | +		.hexsz = GIT_SHA256_HEXSZ, | 
|  | 224 | +		.blksz = GIT_SHA256_BLKSZ, | 
|  | 225 | +		.init_fn = git_hash_sha256_init, | 
|  | 226 | +		.clone_fn = git_hash_sha256_clone, | 
|  | 227 | +		.update_fn = git_hash_sha256_update, | 
|  | 228 | +		.final_fn = git_hash_sha256_final, | 
|  | 229 | +		.final_oid_fn = git_hash_sha256_final_oid, | 
|  | 230 | +		.empty_tree = &empty_tree_oid_sha256, | 
|  | 231 | +		.empty_blob = &empty_blob_oid_sha256, | 
|  | 232 | +		.null_oid = &null_oid_sha256, | 
|  | 233 | +	} | 
|  | 234 | +}; | 
|  | 235 | + | 
|  | 236 | +const struct object_id *null_oid(void) | 
|  | 237 | +{ | 
|  | 238 | +	return the_hash_algo->null_oid; | 
|  | 239 | +} | 
|  | 240 | + | 
|  | 241 | +const char *empty_tree_oid_hex(const struct git_hash_algo *algop) | 
|  | 242 | +{ | 
|  | 243 | +	static char buf[GIT_MAX_HEXSZ + 1]; | 
|  | 244 | +	return oid_to_hex_r(buf, algop->empty_tree); | 
|  | 245 | +} | 
|  | 246 | + | 
|  | 247 | +int hash_algo_by_name(const char *name) | 
|  | 248 | +{ | 
|  | 249 | +	int i; | 
|  | 250 | +	if (!name) | 
|  | 251 | +		return GIT_HASH_UNKNOWN; | 
|  | 252 | +	for (i = 1; i < GIT_HASH_NALGOS; i++) | 
|  | 253 | +		if (!strcmp(name, hash_algos[i].name)) | 
|  | 254 | +			return i; | 
|  | 255 | +	return GIT_HASH_UNKNOWN; | 
|  | 256 | +} | 
|  | 257 | + | 
|  | 258 | +int hash_algo_by_id(uint32_t format_id) | 
|  | 259 | +{ | 
|  | 260 | +	int i; | 
|  | 261 | +	for (i = 1; i < GIT_HASH_NALGOS; i++) | 
|  | 262 | +		if (format_id == hash_algos[i].format_id) | 
|  | 263 | +			return i; | 
|  | 264 | +	return GIT_HASH_UNKNOWN; | 
|  | 265 | +} | 
|  | 266 | + | 
|  | 267 | +int hash_algo_by_length(int len) | 
|  | 268 | +{ | 
|  | 269 | +	int i; | 
|  | 270 | +	for (i = 1; i < GIT_HASH_NALGOS; i++) | 
|  | 271 | +		if (len == hash_algos[i].rawsz) | 
|  | 272 | +			return i; | 
|  | 273 | +	return GIT_HASH_UNKNOWN; | 
|  | 274 | +} | 
|  | 275 | + | 
|  | 276 | +const struct git_hash_algo *unsafe_hash_algo(const struct git_hash_algo *algop) | 
|  | 277 | +{ | 
|  | 278 | +	/* If we have a faster "unsafe" implementation, use that. */ | 
|  | 279 | +	if (algop->unsafe) | 
|  | 280 | +		return algop->unsafe; | 
|  | 281 | +	/* Otherwise use the default one. */ | 
|  | 282 | +	return algop; | 
|  | 283 | +} | 
0 commit comments