1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-31 03:21:24 +03:00

Advance input pointer when LZ4 compressing data

LZ4File_write() did not advance the input pointer on subsequent invocations of
LZ4F_compressUpdate(). As a result the generated compressed output would be a
compressed version of the same input chunk.

Tests failed to catch this error because the data would comfortably fit
within the default buffer size, as a single chunk. Tests have been added
to provide adequate coverage of multi-chunk compression.

WriteDataToArchiveLZ4() which is also using LZ4F_compressUpdate() did
not suffer from this omission.

Author: Georgios Kokolatos <gkokolatos@pm.me>
Reported-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/ZFhCyn4Gm2eu60rB%40paquier.xyz
This commit is contained in:
Tomas Vondra 2023-05-17 16:49:31 +02:00
parent 3c18d90f89
commit 1a05c1d252
3 changed files with 55 additions and 1 deletions

View File

@ -17,7 +17,13 @@
#include "pg_backup_archiver.h"
/* Default size used for IO buffers */
/*
* Default size used for IO buffers
*
* When changing this value, it's necessary to check the relevant test cases
* still exercise all the branches. This applies especially if the value is
* increased, in which case the overflow buffer may not be needed.
*/
#define DEFAULT_IO_BUFFER_SIZE 4096
extern char *supports_compression(const pg_compress_specification compression_spec);

View File

@ -588,6 +588,8 @@ LZ4Stream_write(const void *ptr, size_t size, CompressFileHandle *CFH)
errno = (errno) ? errno : ENOSPC;
return false;
}
ptr = ((const char *) ptr) + chunk;
}
return true;

View File

@ -3108,6 +3108,52 @@ my %tests = (
},
},
'CREATE TABLE test_compression_method' => {
create_order => 110,
create_sql => 'CREATE TABLE dump_test.test_compression_method (
col1 text
);',
regexp => qr/^
\QCREATE TABLE dump_test.test_compression_method (\E\n
\s+\Qcol1 text\E\n
\Q);\E
/xm,
like => {
%full_runs,
%dump_test_schema_runs,
section_pre_data => 1,
},
unlike => {
exclude_dump_test_schema => 1,
only_dump_measurement => 1,
},
},
# Insert enough data to surpass DEFAULT_IO_BUFFER_SIZE during
# (de)compression operations
'COPY test_compression_method' => {
create_order => 111,
create_sql => 'INSERT INTO dump_test.test_compression_method (col1) '
. 'SELECT string_agg(a::text, \'\') FROM generate_series(1,4096) a;',
regexp => qr/^
\QCOPY dump_test.test_compression_method (col1) FROM stdin;\E
\n(?:\d{15277}\n){1}\\\.\n
/xm,
like => {
%full_runs,
data_only => 1,
section_data => 1,
only_dump_test_schema => 1,
test_schema_plus_large_objects => 1,
},
unlike => {
binary_upgrade => 1,
exclude_dump_test_schema => 1,
schema_only => 1,
only_dump_measurement => 1,
},
},
'CREATE TABLE fk_reference_test_table' => {
create_order => 21,
create_sql => 'CREATE TABLE dump_test.fk_reference_test_table (