diff --git a/src/bin/pg_dump/compress_lz4.c b/src/bin/pg_dump/compress_lz4.c index 500d5e16a6d..1dc3a7f05dd 100644 --- a/src/bin/pg_dump/compress_lz4.c +++ b/src/bin/pg_dump/compress_lz4.c @@ -58,6 +58,7 @@ typedef struct LZ4State * decompression operations. */ bool compressing; + bool frame_finished; /* * I/O buffer area. @@ -471,7 +472,14 @@ LZ4Stream_read_internal(LZ4State *state, void *ptr, int ptrsize, bool eol_flag) return -1; } if (rsize == 0) + { + if (!state->frame_finished) + { + state->errcode = EIO; + return -1; + } break; /* must be EOF */ + } state->bufdata = rsize; state->bufnext = 0; } @@ -499,6 +507,8 @@ LZ4Stream_read_internal(LZ4State *state, void *ptr, int ptrsize, bool eol_flag) state->bufnext += inlen; state->outbufdata = outlen; state->outbufnext = 0; + if (status == 0) + state->frame_finished = true; } } diff --git a/src/bin/pg_dump/t/006_pg_dump_compress.pl b/src/bin/pg_dump/t/006_pg_dump_compress.pl index d4ce6b18077..98c2870e92c 100644 --- a/src/bin/pg_dump/t/006_pg_dump_compress.pl +++ b/src/bin/pg_dump/t/006_pg_dump_compress.pl @@ -631,6 +631,33 @@ foreach my $run (sort keys %pgdump_runs) } } +######################################### +# Test that pg_restore rejects a truncated LZ4 stream. + +if ($supports_lz4) +{ + my $source_dir = "$tempdir/compression_lz4_dir"; + my $truncated_dir = "$tempdir/compression_lz4_dir_truncated"; + + system('cp', '-a', $source_dir, $truncated_dir) == 0 + or die "could not copy LZ4 directory archive"; + + my $toc_file = "$truncated_dir/toc.dat.lz4"; + my $size = -s $toc_file; + + truncate($toc_file, $size - 10) + or die "could not truncate $toc_file: $!"; + + $node->command_fails( + [ + 'pg_restore', + '--file' => "$tempdir/compression_lz4_dir_truncated.sql", + '--statistics', + $truncated_dir, + ], + 'pg_restore rejects truncated LZ4 archive'); +} + ######################################### # Stop the database instance, which will be removed at the end of the tests.