summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2023-05-25 12:36:18 +0200
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2023-05-25 12:36:18 +0200
commit34f51196573ca19d83707d30b218c65b46f42d77 (patch)
tree6de2a8b1c3939c51b82c8d6cd9038ebb826550b2
parent4729d1e8aab90bc5861a4ff01fc306ebf1bec433 (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 <exclusion@gmail.com> Discussion: https://postgr.es/m/bcf802a6-afc1-95b9-7bf4-c5dd868ec144@gmail.com
-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 56cf635112d..e0cd7542866 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -3071,6 +3071,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
@@ -3082,23 +3103,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])
{
@@ -3130,13 +3136,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 93b5588d648..027c51317f7 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
}