}
/*
- * Convert a partial SHA1 hex string to the corresponding partial SHA1 value.
- * - hex - Partial SHA1 segment in ASCII hex format
- * - hex_len - Length of above segment. Must be multiple of 2 between 0 and 40
- * - sha1 - Partial SHA1 value is written here
- * - sha1_len - Max #bytes to store in sha1, Must be >= hex_len / 2, and < 20
- * Returns -1 on error (invalid arguments or invalid SHA1 (not in hex format)).
- * Otherwise, returns number of bytes written to sha1 (i.e. hex_len / 2).
- * Pads sha1 with NULs up to sha1_len (not included in returned length).
+ * Read `len` pairs of hexadecimal digits from `hex` and write the
+ * values to `binary` as `len` bytes. Return 0 on success, or -1 if
+ * the input does not consist of hex digits).
*/
-static int get_oid_hex_segment(const char *hex, unsigned int hex_len,
- unsigned char *oid, unsigned int oid_len)
+static int hex_to_bytes(unsigned char *binary, const char *hex, size_t len)
{
- unsigned int i, len = hex_len >> 1;
- if (hex_len % 2 != 0 || len > oid_len)
- return -1;
- for (i = 0; i < len; i++) {
+ for (; len; len--, hex += 2) {
unsigned int val = (hexval(hex[0]) << 4) | hexval(hex[1]);
+
if (val & ~0xff)
return -1;
- *oid++ = val;
- hex += 2;
+ *binary++ = val;
}
- for (; i < oid_len; i++)
- *oid++ = 0;
- return len;
+ return 0;
}
static int non_note_cmp(const struct non_note *a, const struct non_note *b)
struct int_node *node, unsigned int n)
{
struct object_id object_oid;
- unsigned int prefix_len;
+ size_t prefix_len;
void *buf;
struct tree_desc desc;
struct name_entry entry;
- buf = fill_tree_descriptor(&desc, subtree->val_oid.hash);
+ buf = fill_tree_descriptor(&desc, &subtree->val_oid);
if (!buf)
die("Could not read %s for notes-index",
oid_to_hex(&subtree->val_oid));
prefix_len = subtree->key_oid.hash[KEY_INDEX];
- assert(prefix_len * 2 >= n);
+ if (prefix_len >= GIT_SHA1_RAWSZ)
+ BUG("prefix_len (%"PRIuMAX") is out of range", (uintmax_t)prefix_len);
+ if (prefix_len * 2 < n)
+ BUG("prefix_len (%"PRIuMAX") is too small", (uintmax_t)prefix_len);
memcpy(object_oid.hash, subtree->key_oid.hash, prefix_len);
while (tree_entry(&desc, &entry)) {
unsigned char type;
struct leaf_node *l;
- int path_len = strlen(entry.path);
+ size_t path_len = strlen(entry.path);
if (path_len == 2 * (GIT_SHA1_RAWSZ - prefix_len)) {
/* This is potentially the remainder of the SHA-1 */
/* notes must be blobs */
goto handle_non_note;
- if (get_oid_hex_segment(entry.path, path_len,
- object_oid.hash + prefix_len,
- GIT_SHA1_RAWSZ - prefix_len) < 0)
+ if (hex_to_bytes(object_oid.hash + prefix_len, entry.path,
+ GIT_SHA1_RAWSZ - prefix_len))
goto handle_non_note; /* entry.path is not a SHA1 */
type = PTR_TYPE_NOTE;
- l = (struct leaf_node *)
- xcalloc(1, sizeof(struct leaf_node));
- oidcpy(&l->key_oid, &object_oid);
- oidcpy(&l->val_oid, entry.oid);
} else if (path_len == 2) {
/* This is potentially an internal node */
+ size_t len = prefix_len;
if (!S_ISDIR(entry.mode))
/* internal nodes must be trees */
goto handle_non_note;
- if (get_oid_hex_segment(entry.path, 2,
- object_oid.hash + prefix_len,
- GIT_SHA1_RAWSZ - prefix_len) < 0)
+ if (hex_to_bytes(object_oid.hash + len++, entry.path, 1))
goto handle_non_note; /* entry.path is not a SHA1 */
+ /*
+ * Pad the rest of the SHA-1 with zeros,
+ * except for the last byte, where we write
+ * the length:
+ */
+ memset(object_oid.hash + len, 0, GIT_SHA1_RAWSZ - len - 1);
+ object_oid.hash[KEY_INDEX] = (unsigned char)len;
+
type = PTR_TYPE_SUBTREE;
- l = (struct leaf_node *)
- xcalloc(1, sizeof(struct leaf_node));
- oidcpy(&l->key_oid, &object_oid);
- oidcpy(&l->val_oid, entry.oid);
- l->key_oid.hash[KEY_INDEX] = (unsigned char) (prefix_len + 1);
} else {
/* This can't be part of a note */
goto handle_non_note;
}
+ l = xcalloc(1, sizeof(*l));
+ oidcpy(&l->key_oid, &object_oid);
+ oidcpy(&l->val_oid, entry.oid);
if (note_tree_insert(t, node, n, l, type,
combine_notes_concatenate))
die("Failed to load %s %s into notes tree "
{
struct strbuf non_note_path = STRBUF_INIT;
const char *q = oid_to_hex(&subtree->key_oid);
- int i;
+ size_t i;
for (i = 0; i < prefix_len; i++) {
strbuf_addch(&non_note_path, *q++);
strbuf_addch(&non_note_path, *q++);
t->dirty = 0;
if (flags & NOTES_INIT_EMPTY || !notes_ref ||
- get_sha1_treeish(notes_ref, object_oid.hash))
+ get_oid_treeish(notes_ref, &object_oid))
return;
if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, object_oid.hash))
die("Cannot use notes ref %s", notes_ref);