mktree: validate entry type in input
authorJosh Micich <josh.micich@gmail.com>
Thu, 14 May 2009 22:49:10 +0000 (15:49 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 16 May 2009 17:35:45 +0000 (10:35 -0700)
Previously mktree would accept tree entries which had a mismatch between
the declared type and the actual type of object.  Check the actual type of
the object when it is available locally.

Signed-off-by: Josh Micich <josh.micich@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin-mktree.c

index 73b0abbd8d9bb6d3b312c382b72f8a6e9d124cfa..dc4f1a711df0e84657c9f1ea3edcba20c9764e75 100644 (file)
@@ -71,7 +71,8 @@ static void mktree_line(char *buf, size_t len, int line_termination, int allow_m
 {
        char *ptr, *ntr;
        unsigned mode;
-       enum object_type type;
+       enum object_type mode_type; /* object type derived from mode */
+       enum object_type obj_type; /* object type derived from sha */
        char *path;
        unsigned char sha1[20];
 
@@ -94,17 +95,8 @@ static void mktree_line(char *buf, size_t len, int line_termination, int allow_m
        if (S_ISGITLINK(mode))
                allow_missing = 1;
 
-       if (!allow_missing)
-               type = sha1_object_info(sha1, NULL);
-       else
-               type = object_type(mode);
-
-       if (type < 0)
-               die("object %s unavailable", sha1_to_hex(sha1));
 
        *ntr++ = 0; /* now at the beginning of SHA1 */
-       if (type != type_from_string(ptr))
-               die("object type %s mismatch (%s)", ptr, typename(type));
 
        path = ntr + 41;  /* at the beginning of name */
        if (line_termination && path[0] == '"') {
@@ -113,6 +105,37 @@ static void mktree_line(char *buf, size_t len, int line_termination, int allow_m
                        die("invalid quoting");
                path = strbuf_detach(&p_uq, NULL);
        }
+
+       /*
+        * Object type is redundantly derivable three ways.
+        * These should all agree.
+        */
+       mode_type = object_type(mode);
+       if (mode_type != type_from_string(ptr)) {
+               die("entry '%s' object type (%s) doesn't match mode type (%s)",
+                       path, ptr, typename(mode_type));
+       }
+
+       /* Check the type of object identified by sha1 */
+       obj_type = sha1_object_info(sha1, NULL);
+       if (obj_type < 0) {
+               if (allow_missing) {
+                       ; /* no problem - missing objects are presumed to be of the right type */
+               } else {
+                       die("entry '%s' object %s is unavailable", path, sha1_to_hex(sha1));
+               }
+       } else {
+               if (obj_type != mode_type) {
+                       /*
+                        * The object exists but is of the wrong type.
+                        * This is a problem regardless of allow_missing
+                        * because the new tree entry will never be correct.
+                        */
+                       die("entry '%s' object %s is a %s but specified type was (%s)",
+                               path, sha1_to_hex(sha1), typename(obj_type), typename(mode_type));
+               }
+       }
+
        append_to_tree(mode, sha1, path);
 }