]> git.ipfire.org Git - thirdparty/git.git/blobdiff - shell.c
rebase --update-refs: fix loops
[thirdparty/git.git] / shell.c
diff --git a/shell.c b/shell.c
index 811e13b9c9597e9c89bf773a1065819d48a2277c..7ff4109db7058b5677be2fa8775f699b54e4d4f1 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -47,6 +47,8 @@ static void cd_to_homedir(void)
                die("could not chdir to user's home directory");
 }
 
+#define MAX_INTERACTIVE_COMMAND (4*1024*1024)
+
 static void run_shell(void)
 {
        int done = 0;
@@ -67,22 +69,46 @@ static void run_shell(void)
        run_command_v_opt(help_argv, RUN_SILENT_EXEC_FAILURE);
 
        do {
-               struct strbuf line = STRBUF_INIT;
                const char *prog;
                char *full_cmd;
                char *rawargs;
+               size_t len;
                char *split_args;
                const char **argv;
                int code;
                int count;
 
                fprintf(stderr, "git> ");
-               if (git_read_line_interactively(&line) == EOF) {
+
+               /*
+                * Avoid using a strbuf or git_read_line_interactively() here.
+                * We don't want to allocate arbitrary amounts of memory on
+                * behalf of a possibly untrusted client, and we're subject to
+                * OS limits on command length anyway.
+                */
+               fflush(stdout);
+               rawargs = xmalloc(MAX_INTERACTIVE_COMMAND);
+               if (!fgets(rawargs, MAX_INTERACTIVE_COMMAND, stdin)) {
                        fprintf(stderr, "\n");
-                       strbuf_release(&line);
+                       free(rawargs);
                        break;
                }
-               rawargs = strbuf_detach(&line, NULL);
+               len = strlen(rawargs);
+
+               /*
+                * If we truncated due to our input buffer size, reject the
+                * command. That's better than running bogus input, and
+                * there's a good chance it's just malicious garbage anyway.
+                */
+               if (len >= MAX_INTERACTIVE_COMMAND - 1)
+                       die("invalid command format: input too long");
+
+               if (len > 0 && rawargs[len - 1] == '\n') {
+                       if (--len > 0 && rawargs[len - 1] == '\r')
+                               --len;
+                       rawargs[len] = '\0';
+               }
+
                split_args = xstrdup(rawargs);
                count = split_cmdline(split_args, &argv);
                if (count < 0) {