@@ -8,6 +8,7 @@
#include "hex.h"
#include "index-info.h"
#include "quote.h"
+#include "read-cache-ll.h"
#include "strbuf.h"
#include "tree.h"
#include "parse-options.h"
@@ -52,10 +53,23 @@ static void append_to_tree(unsigned mode, struct object_id *oid, const char *pat
{
struct tree_entry *ent;
size_t len = strlen(path);
- if (!literally && strchr(path, '/'))
- die("path %s contains slash", path);
- FLEX_ALLOC_MEM(ent, name, path, len);
+ if (literally) {
+ FLEX_ALLOC_MEM(ent, name, path, len);
+ } else {
+ /* Normalize and validate entry path */
+ if (S_ISDIR(mode)) {
+ while(len > 0 && is_dir_sep(path[len - 1]))
+ len--;
+ }
+ FLEX_ALLOC_MEM(ent, name, path, len);
+
+ if (!verify_path(ent->name, mode))
+ die(_("invalid path '%s'"), path);
+ if (strchr(ent->name, '/'))
+ die("path %s contains slash", path);
+ }
+
ent->mode = mode;
ent->len = len;
oidcpy(&ent->oid, oid);
@@ -169,4 +169,37 @@ test_expect_success '--literally can create invalid trees' '
test_grep "not properly sorted" err
'
+test_expect_success 'mktree validates path' '
+ tree_oid="$(cat tree)" &&
+ blob_oid="$(git rev-parse $tree_oid:a/one)" &&
+ head_oid="$(git rev-parse HEAD)" &&
+
+ # Valid: tree with or without trailing slash, blob without trailing slash
+ {
+ printf "040000 tree $tree_oid\tfolder1/\n" &&
+ printf "040000 tree $tree_oid\tfolder2\n" &&
+ printf "100644 blob $blob_oid\tfile.txt\n"
+ } | git mktree >actual &&
+
+ # Invalid: blob with trailing slash
+ printf "100644 blob $blob_oid\ttest/" |
+ test_must_fail git mktree 2>err &&
+ test_grep "invalid path ${SQ}test/${SQ}" err &&
+
+ # Invalid: dotdot
+ printf "040000 tree $tree_oid\t../" |
+ test_must_fail git mktree 2>err &&
+ test_grep "invalid path ${SQ}../${SQ}" err &&
+
+ # Invalid: dot
+ printf "040000 tree $tree_oid\t." |
+ test_must_fail git mktree 2>err &&
+ test_grep "invalid path ${SQ}.${SQ}" err &&
+
+ # Invalid: .git
+ printf "040000 tree $tree_oid\t.git/" |
+ test_must_fail git mktree 2>err &&
+ test_grep "invalid path ${SQ}.git/${SQ}" err
+'
+
test_done