summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera2023-05-25 10:36:18 +0000
committerAlvaro Herrera2023-05-25 10:36:18 +0000
commit8f5e42d3346924b5d6330208d62ec1b19fdbc110 (patch)
tree84450645d8944e28206b0ec1ad3ac156fec5632d
parentecb968e7e3da69a39d3efab69fa63fe6c8d04b5f (diff)
Fix pgbench in prepared mode with an empty pipeline
It crashes because it references memory that's not allocated in that particular case. Fix by allocating it. Reported-by: Alexander Lakhin <[email protected]> Discussion: https://postgr.es/m/[email protected]
-rw-r--r--src/bin/pgbench/pgbench.c44
-rw-r--r--src/bin/pgbench/t/001_pgbench_with_server.pl2
2 files changed, 28 insertions, 18 deletions
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 7dbb2ed6a77..1d1670d4c2b 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -3050,6 +3050,27 @@ chooseScript(TState *thread)
}
/*
+ * Allocate space for CState->prepared: we need one boolean for each command
+ * of each script.
+ */
+static void
+allocCStatePrepared(CState *st)
+{
+ Assert(st->prepared == NULL);
+
+ st->prepared = pg_malloc(sizeof(bool *) * num_scripts);
+ for (int i = 0; i < num_scripts; i++)
+ {
+ ParsedScript *script = &sql_script[i];
+ int numcmds;
+
+ for (numcmds = 0; script->commands[numcmds] != NULL; numcmds++)
+ ;
+ st->prepared[i] = pg_malloc0(sizeof(bool) * numcmds);
+ }
+}
+
+/*
* Prepare the SQL command from st->use_file at command_num.
*/
static void
@@ -3061,23 +3082,8 @@ prepareCommand(CState *st, int command_num)
if (command->type != SQL_COMMAND)
return;
- /*
- * If not already done, allocate space for 'prepared' flags: one boolean
- * for each command of each script.
- */
if (!st->prepared)
- {
- st->prepared = pg_malloc(sizeof(bool *) * num_scripts);
- for (int i = 0; i < num_scripts; i++)
- {
- ParsedScript *script = &sql_script[i];
- int numcmds;
-
- for (numcmds = 0; script->commands[numcmds] != NULL; numcmds++)
- ;
- st->prepared[i] = pg_malloc0(sizeof(bool) * numcmds);
- }
- }
+ allocCStatePrepared(st);
if (!st->prepared[st->use_file][command_num])
{
@@ -3109,13 +3115,15 @@ prepareCommandsInPipeline(CState *st)
Assert(commands[st->command]->type == META_COMMAND &&
commands[st->command]->meta == META_STARTPIPELINE);
+ if (!st->prepared)
+ allocCStatePrepared(st);
+
/*
* We set the 'prepared' flag on the \startpipeline itself to flag that we
* don't need to do this next time without calling prepareCommand(), even
* though we don't actually prepare this command.
*/
- if (st->prepared &&
- st->prepared[st->use_file][st->command])
+ if (st->prepared[st->use_file][st->command])
return;
for (j = st->command + 1; commands[j] != NULL; j++)
diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl
index 363a1ffabd5..f8ca8a922d1 100644
--- a/src/bin/pgbench/t/001_pgbench_with_server.pl
+++ b/src/bin/pgbench/t/001_pgbench_with_server.pl
@@ -790,6 +790,8 @@ $node->pgbench(
'001_pgbench_pipeline_prep' => q{
-- test startpipeline
\startpipeline
+\endpipeline
+\startpipeline
} . "select 1;\n" x 10 . q{
\endpipeline
}