diff options
| -rw-r--r-- | Makefile.am | 1 | ||||
| -rw-r--r-- | src/blogc-git-receiver/shell.c | 86 | ||||
| -rwxr-xr-x | tests/blogc-git-receiver/check_shell.sh | 73 | 
3 files changed, 112 insertions, 48 deletions
| diff --git a/Makefile.am b/Makefile.am index c4da494..bcfc2ac 100644 --- a/Makefile.am +++ b/Makefile.am @@ -322,6 +322,7 @@ if BUILD_GIT_RECEIVER  dist_check_SCRIPTS += \  	tests/blogc-git-receiver/check_post_receive.sh \  	tests/blogc-git-receiver/check_pre_receive.sh \ +	tests/blogc-git-receiver/check_shell.sh \  	$(NULL)  endif diff --git a/src/blogc-git-receiver/shell.c b/src/blogc-git-receiver/shell.c index 34aa3f2..d83174f 100644 --- a/src/blogc-git-receiver/shell.c +++ b/src/blogc-git-receiver/shell.c @@ -50,27 +50,13 @@ bgr_shell(int argc, char *argv[])          goto cleanup;      } -    repo = bc_strdup_printf("repos/%s", tmp_repo); +    repo = bc_strdup_printf("%s/repos/%s", home, tmp_repo);      quoted_repo = bgr_shell_quote(repo);      free(tmp_repo); -    // check if repository is sane -    if (0 == strlen(repo)) { -        fprintf(stderr, "error: invalid repository\n"); -        rv = 1; -        goto cleanup; -    } -      if (0 == strncmp(argv[2], "git-upload-", 11))  // no need to check len here          goto git_exec; -    if (0 != chdir(home)) { -        fprintf(stderr, "error: failed to chdir (%s): %s\n", home, -            strerror(errno)); -        rv = 1; -        goto cleanup; -    } -      if (0 != access(repo, F_OK)) {          char *git_init_cmd = bc_strdup_printf(              "git init --bare %s > /dev/null", quoted_repo); @@ -85,7 +71,7 @@ bgr_shell(int argc, char *argv[])      }      if (0 != chdir(repo)) { -        fprintf(stderr, "error: failed to chdir (%s/%s): %s\n", home, repo, +        fprintf(stderr, "error: failed to chdir (%s): %s\n", repo,              strerror(errno));          rv = 1;          goto cleanup; @@ -95,16 +81,16 @@ bgr_shell(int argc, char *argv[])          // openwrt git package won't install git templates, then the git          // repositories created with it won't have the hooks/ directory.          if (0 != mkdir("hooks", 0777)) {  // mkdir honors umask for us. -            fprintf(stderr, "error: failed to create directory (%s/%s/hooks): " -                "%s\n", home, repo, strerror(errno)); +            fprintf(stderr, "error: failed to create directory (%s/hooks): " +                "%s\n", repo, strerror(errno));              rv = 1;              goto cleanup;          }      }      if (0 != chdir("hooks")) { -        fprintf(stderr, "error: failed to chdir (%s/%s/hooks): %s\n", home, -            repo, strerror(errno)); +        fprintf(stderr, "error: failed to chdir (%s/hooks): %s\n", repo, +            strerror(errno));          rv = 1;          goto cleanup;      } @@ -112,7 +98,7 @@ bgr_shell(int argc, char *argv[])      if (0 == access("pre-receive", F_OK)) {          if (0 != unlink("pre-receive")) {              fprintf(stderr, "error: failed to remove old symlink " -                "(%s/%s/hooks/pre-receive): %s\n", home, repo, strerror(errno)); +                "(%s/hooks/pre-receive): %s\n", repo, strerror(errno));              rv = 1;              goto cleanup;          } @@ -120,7 +106,7 @@ bgr_shell(int argc, char *argv[])      if (0 != symlink(self, "pre-receive")) {          fprintf(stderr, "error: failed to create symlink " -            "(%s/%s/hooks/pre-receive): %s\n", home, repo, strerror(errno)); +            "(%s/hooks/pre-receive): %s\n", repo, strerror(errno));          rv = 1;          goto cleanup;      } @@ -128,7 +114,7 @@ bgr_shell(int argc, char *argv[])      if (0 == access("post-receive", F_OK)) {          if (0 != unlink("post-receive")) {              fprintf(stderr, "error: failed to remove old symlink " -                "(%s/%s/hooks/post-receive): %s\n", home, repo, strerror(errno)); +                "(%s/hooks/post-receive): %s\n", repo, strerror(errno));              rv = 1;              goto cleanup;          } @@ -136,11 +122,13 @@ bgr_shell(int argc, char *argv[])      if (0 != symlink(self, "post-receive")) {          fprintf(stderr, "error: failed to create symlink " -            "(%s/%s/hooks/post-receive): %s\n", home, repo, strerror(errno)); +            "(%s/hooks/post-receive): %s\n", repo, strerror(errno));          rv = 1;          goto cleanup;      } +git_exec: +      if (0 != chdir(home)) {          fprintf(stderr, "error: failed to chdir (%s): %s\n", home,              strerror(errno)); @@ -148,40 +136,42 @@ bgr_shell(int argc, char *argv[])          goto cleanup;      } -git_exec: +    // static allocation instead of bc_strdup_printf to avoid leaks +    char buffer[4096]; +    char *command = bc_strdup(argv[2]); +    char *p; +    for (p = command; *p != ' ' && *p != '\0'; p++); +    if (*p == ' ') +        *p = '\0'; -    { -        // static allocation instead of bc_strdup_printf to avoid leaks -        char buffer[4096]; -        char *command = bc_strdup(argv[2]); -        char *p; -        for (p = command; *p != ' ' && *p != '\0'; p++); -        if (*p == ' ') -            *p = '\0'; - -        if (sizeof(buffer) < (strlen(command) + strlen(quoted_repo) + 2)) { -            fprintf(stderr, "error: git-shell command is too big\n"); -            rv = 1; -            goto cleanup; -        } +    if (sizeof(buffer) < (strlen(command) + strlen(quoted_repo) + 2)) { +        fprintf(stderr, "error: git-shell command is too big\n"); +        rv = 1; +        goto cleanup; +    } -        if (0 > snprintf(buffer, sizeof(buffer), "%s %s", command, quoted_repo)) { -            fprintf(stderr, "error: failed to generate git-shell command\n"); -            rv = 1; -            goto cleanup; -        } +    if (0 > snprintf(buffer, sizeof(buffer), "%s %s", command, quoted_repo)) { +        fprintf(stderr, "error: failed to generate git-shell command\n"); +        rv = 1; +        goto cleanup; +    } -        free(command); -        free(repo); -        free(quoted_repo); +    free(command); +    free(repo); +    free(quoted_repo); +    // this is a hack. no memory handling should be done inside this block +    if (NULL == getenv("__VALGRIND_ENABLED")) {          execlp("git-shell", "git-shell", "-c", buffer, NULL);          // execlp only returns on error, then something bad happened          fprintf(stderr, "error: failed to execute git-shell\n"); -        return 1;  // avoid freeing repo again +        return 1;      } +    printf("git-shell -c \"%s\"\n", buffer);  // used by tests, ignore +    return 0; +  cleanup:      free(repo);      free(quoted_repo); diff --git a/tests/blogc-git-receiver/check_shell.sh b/tests/blogc-git-receiver/check_shell.sh new file mode 100755 index 0000000..0367f96 --- /dev/null +++ b/tests/blogc-git-receiver/check_shell.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +set -xe -o pipefail + +export LC_ALL=C + +TEMP="$(mktemp -d)" +[[ -n "${TEMP}" ]] + +trap_func() { +    [[ -e "${TEMP}/output.txt" ]] && cat "${TEMP}/output.txt" +    rm -rf "${TEMP}" +} + +trap trap_func EXIT + +SELF="${PWD}/blogc-git-receiver" + +call_bgr() { +    [[ -n "${VALGRIND}" ]] && export __VALGRIND_ENABLED=1 +    SHELL="${SELF}" HOME="${TEMP}" ${TESTS_ENVIRONMENT} "${SELF}" "$@" +} + +call_bgr -c "bola 'lol.git'" 2>&1 | tee "${TEMP}/output.txt" || true +grep "error: invalid git-shell command: bola 'lol\.git'" "${TEMP}/output.txt" &> /dev/null + +echo 0000 | call_bgr -c "git-receive-pack 'lol.git'" 2>&1 > "${TEMP}/output.txt" +if [[ -n "${VALGRIND}" ]]; then +    grep "git-shell -c \"git-receive-pack '.*repos/lol.git'\"" "${TEMP}/output.txt" &> /dev/null +else +    grep "agent=" "${TEMP}/output.txt" &> /dev/null +fi +[[ -d "${TEMP}/repos/lol.git" ]] +[[ -h "${TEMP}/repos/lol.git/hooks/pre-receive" ]] +[[ "$(readlink "${TEMP}/repos/lol.git/hooks/pre-receive")" == "${SELF}" ]] +[[ -h "${TEMP}/repos/lol.git/hooks/post-receive" ]] +[[ "$(readlink "${TEMP}/repos/lol.git/hooks/post-receive")" == "${SELF}" ]] + +cat > "${TEMP}/tmp.txt" <<EOF +blob +mark :1 +data 4 +bar + +reset refs/heads/master +commit refs/heads/master +mark :2 +author Rafael G. Martins <rafael@rafaelmartins.eng.br> 1476033730 +0200 +committer Rafael G. Martins <rafael@rafaelmartins.eng.br> 1476033888 +0200 +data 11 +testing... +M 100644 :1 foo + +EOF +cd "${TEMP}/repos/lol.git" +git fast-import < "${TEMP}/tmp.txt" &> /dev/null +cd - > /dev/null + +echo 0000 | call_bgr -c "git-upload-pack 'lol.git'" 2>&1 > "${TEMP}/output.txt" +if [[ -n "${VALGRIND}" ]]; then +    grep "git-shell -c \"git-upload-pack '.*repos/lol.git'\"" "${TEMP}/output.txt" &> /dev/null +else +    grep "agent=" "${TEMP}/output.txt" &> /dev/null +fi + +echo 0000 | call_bgr -c "git-upload-archive 'lol.git'" 2>&1 > "${TEMP}/output.txt" || true +if [[ -n "${VALGRIND}" ]]; then +    grep "git-shell -c \"git-upload-archive '.*repos/lol.git'\"" "${TEMP}/output.txt" &> /dev/null +else +    grep "ACK" "${TEMP}/output.txt" &> /dev/null +fi + +rm "${TEMP}/output.txt" | 
