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:20:41 +0000 (17:20 +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 1a1cc520f3430f6b95abc7ac073a6a0deb8bb3eb..f482c1c28b3ded8d6d02491d3e406471f86958ba 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
@@ -227,6 +227,12 @@ pattern_compare(char *str, const int type, const char *param_name)
        }
 
        s = strip_quote(str);
+       if (!s)
+       {
+               elog(WARNING, "pattern_compare: strip_quote() returns error");
+               return -1;
+       }
+
        for (i = 0; i < *pattc; i++)
        {
                if (lists_patterns[i].type != type)
@@ -271,13 +277,31 @@ pattern_compare(char *str, const int type, const char *param_name)
        return result;
 }
 
+/*
+ * 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                len;
        int                     i = 0;
 
-       after = malloc(sizeof(char) * strlen(str) + 1);
+       len = strlen(str);
+       after = malloc(sizeof(char) * len + 1);
+       if (!after)
+       {
+               return NULL;
+       }
+
+       if (len == 0)
+       {
+               /* empty string case */
+               *after = '\0';
+               return after;
+       }
 
        do
        {