ecpg: fix some minor mishandling of bad input in preprocessor.
authorTom Lane <[email protected]>
Wed, 16 Oct 2024 16:24:57 +0000 (12:24 -0400)
committerTom Lane <[email protected]>
Wed, 16 Oct 2024 16:25:00 +0000 (12:25 -0400)
Avoid null-pointer crash when considering a cursor declaration
that's outside any C function (a case which is useless anyway).

Ensure a cursor for a prepared statement is marked as initially
not open.  At worst, if we chanced to get not-already-zeroed memory
from malloc(), this oversight would result in failing to issue a
"cursor "foo" has been declared but not opened" warning that would
have been appropriate.

Avoid running off the end of the buffer when there are mismatched
square brackets following a variable name.  This could lead to
SIGSEGV after reaching the end of memory.

Given the lack of field complaints, none of these seem to be worth
back-patching, but let's clean them up in HEAD.

Per valgrind testing by Alexander Lakhin.

Discussion: https://postgr.es/m/5f5bcecd-d7ec-b8c0-6c92-d1a7c6e0f639@gmail.com

src/interfaces/ecpg/preproc/ecpg.header
src/interfaces/ecpg/preproc/ecpg.trailer
src/interfaces/ecpg/preproc/variable.c

index d3df8eabbb731914d75825e17daaa26587c1fc43..a415780faffeac8bd60282b9b63eb3911227a5df 100644 (file)
@@ -432,7 +432,8 @@ adjust_outofscope_cursor_vars(struct cursor *cur)
 /* This tests whether the cursor was declared and opened in the same function. */
 #define SAMEFUNC(cur)  \
    ((cur->function == NULL) ||     \
-    (cur->function != NULL && strcmp(cur->function, current_function) == 0))
+    (cur->function != NULL && current_function != NULL && \
+     strcmp(cur->function, current_function) == 0))
 
 static struct cursor *
 add_additional_variables(const char *name, bool insert)
index 0a77559e83b4a2f5ededfa9566e53a4f44603697..e466668ea2446990b961e7bea4c75bf75404009f 100644 (file)
@@ -433,6 +433,7 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_
        this->name = mm_strdup(@2);
        this->function = (current_function ? mm_strdup(current_function) : NULL);
        this->connection = connection ? mm_strdup(connection) : NULL;
+       this->opened = false;
        this->command = mm_strdup(cat_str(6, "declare", cursor_marker, @3, "cursor", @5, "for $1"));
        this->argsresult = NULL;
        this->argsresult_oos = NULL;
index 6b87d5ff3d9edae8e36e6a6985a6834bda1b20d5..a4294b8f0ff94bef5c2d86f68aa8f2a7dbc30fe2 100644 (file)
@@ -216,6 +216,9 @@ find_variable(const char *name)
                    case ']':
                        count--;
                        break;
+                   case '\0':
+                       mmfatal(PARSE_ERROR, "unmatched brace in variable \"%s\"", name);
+                       break;
                    default:
                        break;
                }