Skip to content

Commit d3c945f

Browse files
alvherrepull[bot]
authored andcommitted
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
1 parent c186490 commit d3c945f

File tree

2 files changed

+28
-18
lines changed

2 files changed

+28
-18
lines changed

src/bin/pgbench/pgbench.c

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3049,6 +3049,27 @@ chooseScript(TState *thread)
30493049
return i - 1;
30503050
}
30513051

3052+
/*
3053+
* Allocate space for CState->prepared: we need one boolean for each command
3054+
* of each script.
3055+
*/
3056+
static void
3057+
allocCStatePrepared(CState *st)
3058+
{
3059+
Assert(st->prepared == NULL);
3060+
3061+
st->prepared = pg_malloc(sizeof(bool *) * num_scripts);
3062+
for (int i = 0; i < num_scripts; i++)
3063+
{
3064+
ParsedScript *script = &sql_script[i];
3065+
int numcmds;
3066+
3067+
for (numcmds = 0; script->commands[numcmds] != NULL; numcmds++)
3068+
;
3069+
st->prepared[i] = pg_malloc0(sizeof(bool) * numcmds);
3070+
}
3071+
}
3072+
30523073
/*
30533074
* Prepare the SQL command from st->use_file at command_num.
30543075
*/
@@ -3061,23 +3082,8 @@ prepareCommand(CState *st, int command_num)
30613082
if (command->type != SQL_COMMAND)
30623083
return;
30633084

3064-
/*
3065-
* If not already done, allocate space for 'prepared' flags: one boolean
3066-
* for each command of each script.
3067-
*/
30683085
if (!st->prepared)
3069-
{
3070-
st->prepared = pg_malloc(sizeof(bool *) * num_scripts);
3071-
for (int i = 0; i < num_scripts; i++)
3072-
{
3073-
ParsedScript *script = &sql_script[i];
3074-
int numcmds;
3075-
3076-
for (numcmds = 0; script->commands[numcmds] != NULL; numcmds++)
3077-
;
3078-
st->prepared[i] = pg_malloc0(sizeof(bool) * numcmds);
3079-
}
3080-
}
3086+
allocCStatePrepared(st);
30813087

30823088
if (!st->prepared[st->use_file][command_num])
30833089
{
@@ -3109,13 +3115,15 @@ prepareCommandsInPipeline(CState *st)
31093115
Assert(commands[st->command]->type == META_COMMAND &&
31103116
commands[st->command]->meta == META_STARTPIPELINE);
31113117

3118+
if (!st->prepared)
3119+
allocCStatePrepared(st);
3120+
31123121
/*
31133122
* We set the 'prepared' flag on the \startpipeline itself to flag that we
31143123
* don't need to do this next time without calling prepareCommand(), even
31153124
* though we don't actually prepare this command.
31163125
*/
3117-
if (st->prepared &&
3118-
st->prepared[st->use_file][st->command])
3126+
if (st->prepared[st->use_file][st->command])
31193127
return;
31203128

31213129
for (j = st->command + 1; commands[j] != NULL; j++)

src/bin/pgbench/t/001_pgbench_with_server.pl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,8 @@
790790
'001_pgbench_pipeline_prep' => q{
791791
-- test startpipeline
792792
\startpipeline
793+
\endpipeline
794+
\startpipeline
793795
} . "select 1;\n" x 10 . q{
794796
\endpipeline
795797
}

0 commit comments

Comments
 (0)