]> git.saurik.com Git - redis.git/commitdiff
Add tests for quotation in an interactive redis-cli session
authorPieter Noordhuis <pcnoordhuis@gmail.com>
Wed, 4 Aug 2010 13:29:28 +0000 (15:29 +0200)
committerPieter Noordhuis <pcnoordhuis@gmail.com>
Wed, 4 Aug 2010 14:15:33 +0000 (16:15 +0200)
Patched redis-cli to abort on unexpected quotation. This caused
redis-cli to get into an infinite, memory-consuming loop.

src/redis-cli.c
tests/integration/redis-cli.tcl

index 97a119c8cd9afe7aa74f30708c81153c4a08f221..87ebcb69951840597451dab3b2a9652f419525ca 100644 (file)
@@ -378,7 +378,7 @@ static char **splitArguments(char *line, int *argc) {
         if (*p) {
             /* get a token */
             int inq=0; /* set to 1 if we are in "quotes" */
-            int done = 0;
+            int done=0;
 
             if (current == NULL) current = sdsempty();
             while(!done) {
@@ -397,7 +397,12 @@ static char **splitArguments(char *line, int *argc) {
                         }
                         current = sdscatlen(current,&c,1);
                     } else if (*p == '"') {
-                        done = 1;
+                        /* closing quote must be followed by a space */
+                        if (*(p+1) && !isspace(*(p+1))) goto err;
+                        done=1;
+                    } else if (!*p) {
+                        /* unterminated quotes */
+                        goto err;
                     } else {
                         current = sdscatlen(current,p,1);
                     }
@@ -429,6 +434,13 @@ static char **splitArguments(char *line, int *argc) {
             return vector;
         }
     }
+
+err:
+    while(*argc--)
+        sdsfree(vector[*argc]);
+    zfree(vector);
+    if (current) sdsfree(current);
+    return NULL;
 }
 
 #define LINE_BUFLEN 4096
@@ -441,7 +453,10 @@ static void repl() {
             argv = splitArguments(line,&argc);
             linenoiseHistoryAdd(line);
             if (config.historyfile) linenoiseHistorySave(config.historyfile);
-            if (argc > 0) {
+            if (argv == NULL) {
+                printf("Invalid argument(s)\n");
+                continue;
+            } else if (argc > 0) {
                 if (strcasecmp(argv[0],"quit") == 0 ||
                     strcasecmp(argv[0],"exit") == 0)
                         exit(0);
index 191c6598b6833006851f2f0e48a0e88f45b5be0f..6e1061351d6092acff6bdcf26b9e5a3c72560288 100644 (file)
@@ -66,4 +66,23 @@ start_server {tags {"cli"}} {
         r rpush list bar
         assert_equal "1. \"foo\"\n2. \"bar\"" [run_command $fd "lrange list 0 -1"]
     }
+
+    test_interactive_cli "Parsing quotes" {
+        assert_equal "OK" [run_command $fd "set key \"bar\""]
+        assert_equal "bar" [r get key]
+        assert_equal "OK" [run_command $fd "set key \" bar \""]
+        assert_equal " bar " [r get key]
+        assert_equal "OK" [run_command $fd "set key \"\\\"bar\\\"\""]
+        assert_equal "\"bar\"" [r get key]
+        assert_equal "OK" [run_command $fd "set key \"\tbar\t\""]
+        assert_equal "\tbar\t" [r get key]
+
+        # invalid quotation
+        assert_equal "Invalid argument(s)" [run_command $fd "get \"\"key"]
+        assert_equal "Invalid argument(s)" [run_command $fd "get \"key\"x"]
+
+        # quotes after the argument are weird, but should be allowed
+        assert_equal "OK" [run_command $fd "set key\"\" bar"]
+        assert_equal "bar" [r get key]
+    }
 }