Fix execute() in memory allocation logic when memqcache enabled.
authorTatsuo Ishii <ishii@postgresql.org>
Tue, 2 Jul 2013 08:13:10 +0000 (17:13 +0900)
committerTatsuo Ishii <ishii@postgresql.org>
Tue, 2 Jul 2013 08:13:10 +0000 (17:13 +0900)
When very long query string (>1024) supplied in extended query with
bind parameters, it fails to allocate enough memory.

pool_proto_modules.c

index 56e1e3af0f3a19c1fc86a8ca47a488a705b93ca4..556baca84bfab6de23f97da85986e012f7439006 100644 (file)
@@ -706,10 +706,15 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
                bool foundp;
                POOL_STATUS status;
                char *search_query = NULL;
+               int len;
+               char *tmp;
+#define STR_ALLOC_SIZE 1024
 
-               search_query = (char *)malloc(sizeof(char) * strlen(query) + 1);
+               len = strlen(query)+1;
+               search_query = (char *)malloc(len);
                if (search_query == NULL)
                {
+                       pool_error("Execute: malloc failed");
                        return POOL_END;
                }
                strcpy(search_query, query);
@@ -722,26 +727,36 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
                        /* Extract binary contents from bind message */
                        char *query_in_bind_msg = bind_msg->contents + bind_msg->param_offset;
                        char hex_str[4];  /* 02X chars + white space + null end */
-                       int max_search_query_size = 0;
-                       int i = 0;
-                       char *tmp;
+                       int i;
+                       int alloc_len;
+
+                       alloc_len = (len/STR_ALLOC_SIZE+1)*STR_ALLOC_SIZE;
+                       search_query = realloc(search_query, alloc_len);
+                       if (search_query == NULL)
+                       {
+                               pool_error("Execute: realloc failed");
+                               return POOL_END;
+                       }
 
                        for (i = 0; i < bind_msg->len - bind_msg->param_offset; i++)
                        {
-                               while (max_search_query_size <= sizeof(char) * strlen(search_query))
+                               int hexlen;
+
+                               snprintf(hex_str, sizeof(hex_str), (i == 0) ? " %02X" : "%02X", 0xff & query_in_bind_msg[i]);
+                               hexlen = strlen(hex_str);
+
+                               if ((len+hexlen) > alloc_len)
                                {
-                                       max_search_query_size += 1024;
-                                       tmp = (char *)realloc(search_query, sizeof(char) * max_search_query_size);
-                                       if (tmp == NULL)
+                                       alloc_len += STR_ALLOC_SIZE;
+                                       search_query = realloc(search_query, alloc_len);
+                                       if (search_query == NULL)
                                        {
+                                               pool_error("Execute: realloc failed");
                                                return POOL_END;
                                        }
-                                       search_query = tmp;
-                                       tmp = NULL;
                                }
-
-                               snprintf(hex_str, sizeof(hex_str), (i == 0) ? " %02X" : "%02X", 0xff & query_in_bind_msg[i]);
                                strcat(search_query, hex_str);
+                               len += hexlen;
                        }
 
                        query_context->query_w_hex = search_query;
@@ -764,6 +779,7 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend,
                                tmp = (char *)malloc(sizeof(char) * strlen(search_query) + 1);
                                if (tmp == NULL)
                                {
+                                       pool_error("Execute: malloc failed");
                                        return POOL_END;
                                }
                                free(query_context->temp_cache->query);