Skip to content

Commit 8f5e42d

Browse files
committed
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 ecb968e commit 8f5e42d

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)