Skip to content

Commit afb529e

Browse files
committed
pg_basebackup: Fix code that thinks about LZ4 buffer size.
Before this patch, there was some code that tried to make sure that the buffer was always big enough at the start, and then asserted that it didn't need to be enlarged later. However, the code to make sure it was big enough at the start doesn't actually work, and therefore it was possible to fail an assertion and crash later. Remove the code that tries to make sure the buffer is always big enough at the start in favor of enlarging the buffer as we go along whenever that is necessary. The mistake probably happened because, on the server side, we do actually need to guarantee that the buffer is big enough at the start to avoid subsequent resizings. However, in that case, the calling code makes promises about how much data it will provide at once, but here, that's not the case. Report by Justin Pryzby. Analysis by me. Patch by Dipesh Pandit. Discussion: http://postgr.es/m/20220330143536.GG28503@telsasoft.com
1 parent 40af10b commit afb529e

File tree

1 file changed

+8
-14
lines changed

1 file changed

+8
-14
lines changed

src/bin/pg_basebackup/bbstreamer_lz4.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ bbstreamer_lz4_compressor_new(bbstreamer *next, bc_specification *compress)
7373
bbstreamer_lz4_frame *streamer;
7474
LZ4F_errorCode_t ctxError;
7575
LZ4F_preferences_t *prefs;
76-
size_t compressed_bound;
7776

7877
Assert(next != NULL);
7978

@@ -92,17 +91,6 @@ bbstreamer_lz4_compressor_new(bbstreamer *next, bc_specification *compress)
9291
if ((compress->options & BACKUP_COMPRESSION_OPTION_LEVEL) != 0)
9392
prefs->compressionLevel = compress->level;
9493

95-
/*
96-
* Find out the compression bound, it specifies the minimum destination
97-
* capacity required in worst case for the success of compression operation
98-
* (LZ4F_compressUpdate) based on a given source size and preferences.
99-
*/
100-
compressed_bound = LZ4F_compressBound(streamer->base.bbs_buffer.maxlen, prefs);
101-
102-
/* Enlarge buffer if it falls short of compression bound. */
103-
if (streamer->base.bbs_buffer.maxlen < compressed_bound)
104-
enlargeStringInfo(&streamer->base.bbs_buffer, compressed_bound);
105-
10694
ctxError = LZ4F_createCompressionContext(&streamer->cctx, LZ4F_VERSION);
10795
if (LZ4F_isError(ctxError))
10896
pg_log_error("could not create lz4 compression context: %s",
@@ -170,14 +158,17 @@ bbstreamer_lz4_compressor_content(bbstreamer *streamer,
170158
* forward the content to next streamer and empty the buffer.
171159
*/
172160
out_bound = LZ4F_compressBound(len, &mystreamer->prefs);
173-
Assert(mystreamer->base.bbs_buffer.maxlen >= out_bound);
174161
if (avail_out < out_bound)
175162
{
176163
bbstreamer_content(mystreamer->base.bbs_next, member,
177164
mystreamer->base.bbs_buffer.data,
178165
mystreamer->bytes_written,
179166
context);
180167

168+
/* Enlarge buffer if it falls short of out bound. */
169+
if (mystreamer->base.bbs_buffer.maxlen < out_bound)
170+
enlargeStringInfo(&mystreamer->base.bbs_buffer, out_bound);
171+
181172
avail_out = mystreamer->base.bbs_buffer.maxlen;
182173
mystreamer->bytes_written = 0;
183174
next_out = (uint8 *) mystreamer->base.bbs_buffer.data;
@@ -218,7 +209,6 @@ bbstreamer_lz4_compressor_finalize(bbstreamer *streamer)
218209

219210
/* Find out the footer bound and update the output buffer. */
220211
footer_bound = LZ4F_compressBound(0, &mystreamer->prefs);
221-
Assert(mystreamer->base.bbs_buffer.maxlen >= footer_bound);
222212
if ((mystreamer->base.bbs_buffer.maxlen - mystreamer->bytes_written) <
223213
footer_bound)
224214
{
@@ -227,6 +217,10 @@ bbstreamer_lz4_compressor_finalize(bbstreamer *streamer)
227217
mystreamer->bytes_written,
228218
BBSTREAMER_UNKNOWN);
229219

220+
/* Enlarge buffer if it falls short of footer bound. */
221+
if (mystreamer->base.bbs_buffer.maxlen < footer_bound)
222+
enlargeStringInfo(&mystreamer->base.bbs_buffer, footer_bound);
223+
230224
avail_out = mystreamer->base.bbs_buffer.maxlen;
231225
mystreamer->bytes_written = 0;
232226
next_out = (uint8 *) mystreamer->base.bbs_buffer.data;

0 commit comments

Comments
 (0)