Fix corner case bug with strip_quote().
authorTatsuo Ishii <ishii@sraoss.co.jp>
Tue, 29 Jan 2019 08:20:41 +0000 (17:20 +0900)
committerTatsuo Ishii <ishii@sraoss.co.jp>
Tue, 29 Jan 2019 08:38:47 +0000 (17:38 +0900)
strip_quote(), which is called by pattern_compare() did not properly
handle empty query string case. In the worst case it could wipe out
memory after a pointer returned from malloc(), which could cause a
segmentation fault in free() called in pattern_compare().

Per bug 458.

src/utils/pool_select_walker.c

index 8ed75e8c0ad91dfc046668af91f1020eb8aee85d..107db3ed365049a461fd1b34b73adefa8b1ff5d3 100644 (file)
@@ -3,7 +3,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2018     PgPool Global Development Group
+ * Copyright (c) 2003-2019     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -191,7 +191,14 @@ int pattern_compare(char *str, const int type, const char *param_name)
        }
 
        s = strip_quote(str);
-       for (i = 0; i < *pattc; i++) {
+       if (!s)
+       {
+               elog(WARNING, "pattern_compare: strip_quote() returns error");
+               return -1;
+       }
+
+       for (i = 0; i < *pattc; i++)
+       {
                if (lists_patterns[i].type != type)
                        continue;
 
@@ -233,12 +240,31 @@ int pattern_compare(char *str, const int type, const char *param_name)
        return result;
 }
 
-static char *strip_quote(char *str)
+/*
+ * Returns double quotes stripped version of malloced string.
+ * Callers must free() after using it.
+ * Returns NULL on error.
+ */
+static char *
+strip_quote(char *str)
 {
-       char *after;
-       int i = 0;
+       char       *after;
+       int                len;
+       int                     i = 0;
+
+       len = strlen(str);
+       after = malloc(sizeof(char) * len + 1);
+       if (!after)
+       {
+               return NULL;
+       }
 
-       after = malloc(sizeof(char) * strlen(str) + 1);
+       if (len == 0)
+       {
+               /* empty string case */
+               *after = '\0';
+               return after;
+       }
 
        do {
                if (*str != '"')