commit f77a24b0362de269128c9588d65818958a9ec9a9 from: Stefan Sperling date: Mon Mar 11 13:58:06 2019 UTC validate ref names commit - 01b7ba6b7375d24a087d44aa48c0b78d66a6187e commit + f77a24b0362de269128c9588d65818958a9ec9a9 blob - f6f99ad590182ea6fbbc1c325681cd23eda29ec4 blob + 65ff442b096e36f03c632555fd6def55aea92bc4 --- include/got_error.h +++ include/got_error.h @@ -78,6 +78,7 @@ #define GOT_ERR_UUID_INVALID 62 #define GOT_ERR_UUID 63 #define GOT_ERR_LOCKFILE_TIMEOUT 64 +#define GOT_ERR_BAD_REF_NAME 65 static const struct got_error { int code; @@ -146,6 +147,7 @@ static const struct got_error { { GOT_ERR_UUID_INVALID, "uuid invalid" }, { GOT_ERR_UUID, "uuid error" }, { GOT_ERR_LOCKFILE_TIMEOUT,"lockfile timeout" }, + { GOT_ERR_BAD_REF_NAME, "bad reference name" }, }; /* blob - adbeed13ac643c78f48533f886ec943ad7de7be0 blob + 9e9655183bf6af53d89c2fcea53352d7d2a47b3e --- lib/reference.c +++ lib/reference.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #include "got_lib_delta.h" #include "got_lib_inflate.h" #include "got_lib_object.h" +#include "got_lib_lockfile.h" #ifndef nitems #define nitems(_a) (sizeof(_a) / sizeof((_a)[0])) @@ -157,6 +159,61 @@ get_refs_dir_path(struct got_repository *repo, const c return strdup(got_repo_get_path_git_dir(repo)); return got_repo_get_path_refs(repo); +} + +static int +is_valid_ref_name(const char *name) +{ + const char *s, *slash, *seg; + const char forbidden[] = { ' ', '~', '^', ':', '?', '*', '[' , '\\' }; + const char *forbidden_seq[] = { "//", "..", "@{" }; + const char *lfs = GOT_LOCKFILE_SUFFIX; + const size_t lfs_len = sizeof(GOT_LOCKFILE_SUFFIX) - 1; + int i; + + if (name[0] == '@' && name[1] == '\0') + return 0; + + slash = strchr(name, '/'); + if (slash == NULL) + return 0; + + s = name; + seg = s; + if (seg[0] == '\0' || seg[0] == '.' || seg[0] == '/') + return 0; + while (*s) { + for (i = 0; i < nitems(forbidden); i++) { + if (*s == forbidden[i]) + return 0; + } + for (i = 0; i < nitems(forbidden_seq); i++) { + if (s[0] == forbidden_seq[i][0] && + s[1] == forbidden_seq[i][1]) + return 0; + } + if (iscntrl((unsigned char)s[0])) + return 0; + if (s[0] == '.' && s[1] == '\0') + return 0; + if (*s == '/') { + const char *nextseg = s + 1; + if (nextseg[0] == '\0' || nextseg[0] == '.' || + nextseg[0] == '/') + return 0; + if (seg <= s - lfs_len && + strncmp(s - lfs_len, lfs, lfs_len) == 0) + return 0; + seg = nextseg; + } + s++; + } + + if (seg <= s - lfs_len && + strncmp(s - lfs_len, lfs, lfs_len) == 0) + return 0; + + return 1; } const struct got_error * @@ -165,6 +222,9 @@ got_ref_alloc(struct got_reference **ref, const char * { const struct got_error *err = NULL; + if (!is_valid_ref_name(name)) + return got_error(GOT_ERR_BAD_REF_NAME); + *ref = calloc(1, sizeof(**ref)); if (*ref == NULL) return got_error_from_errno();