diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2023-05-25 12:36:18 +0200 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2023-05-25 12:36:18 +0200 |
commit | 8f5e42d3346924b5d6330208d62ec1b19fdbc110 (patch) | |
tree | 84450645d8944e28206b0ec1ad3ac156fec5632d | |
parent | ecb968e7e3da69a39d3efab69fa63fe6c8d04b5f (diff) | |
download | postgresql-8f5e42d3346924b5d6330208d62ec1b19fdbc110.tar.gz postgresql-8f5e42d3346924b5d6330208d62ec1b19fdbc110.zip |
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.c | 44 | ||||
-rw-r--r-- | src/bin/pgbench/t/001_pgbench_with_server.pl | 2 |
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 } |