Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6103d2c

Browse files
committed
Fail hard on out-of-memory failures in xlogreader.c
This commit changes the WAL reader routines so as a FATAL for thebackend or exit(FAILURE) for the frontend is triggered if an allocationfor a WAL record decode fails in walreader.c, rather than treating thiscase as bogus data, which would be equivalent to the end of WAL. Thekey is to avoid palloc_extended(MCXT_ALLOC_NO_OOM) in walreader.c,relying on plain palloc() calls.The previous behavior could make WAL replay finish too early than itshould. For example, crash recovery finishing earlier may corruptclusters because not all the WAL available locally was replayed toensure a consistent state. Out-of-memory failures would show uprandomly depending on the memory pressure on the host, but one simplecase would be to generate a large record, then replay this record afterdownsizing a host, as Ethan Mertz originally reported.This relies onbae868c, as the WAL reader routines now do thememory allocation required for a record only once its header has beenfully read and validated, making xl_tot_len trustable. Making the WALreader react differently on out-of-memory or bogus record data wouldrequire ABI changes, so this is the safest choice for stable branches.Also, it is worth noting that3f1ce97 has been using a plainpalloc() in this code for some time now.Thanks to Noah Misch and Thomas Munro for the discussion.Like the other commit, backpatch down to 12, leaving out v11 that willbe EOL'd soon. The behavior of considering a failed allocation as bogusdata comes originally from0ffe11a, where the record lengthretrieved from its header was not entirely trustable.Reported-by: Ethan MertzDiscussion:https://postgr.es/m/ZRKKdI5-RRlta3aF@paquier.xyzBackpatch-through: 12
1 parent295953f commit6103d2c

File tree

1 file changed

+5
-27
lines changed

1 file changed

+5
-27
lines changed

‎src/backend/access/transam/xlogreader.c

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
staticvoidreport_invalid_record(XLogReaderState*state,constchar*fmt,...)
3737
pg_attribute_printf(2,3);
38-
staticboolallocate_recordbuf(XLogReaderState*state,uint32reclength);
38+
staticvoidallocate_recordbuf(XLogReaderState*state,uint32reclength);
3939
staticintReadPageInternal(XLogReaderState*state,XLogRecPtrpageptr,
4040
intreqLen);
4141
staticvoidXLogReaderInvalReadState(XLogReaderState*state);
@@ -124,14 +124,7 @@ XLogReaderAllocate(int wal_segment_size, const char *waldir,
124124
* Allocate an initial readRecordBuf of minimal size, which can later be
125125
* enlarged if necessary.
126126
*/
127-
if (!allocate_recordbuf(state,0))
128-
{
129-
pfree(state->errormsg_buf);
130-
pfree(state->readBuf);
131-
pfree(state);
132-
returnNULL;
133-
}
134-
127+
allocate_recordbuf(state,0);
135128
returnstate;
136129
}
137130

@@ -160,7 +153,6 @@ XLogReaderFree(XLogReaderState *state)
160153

161154
/*
162155
* Allocate readRecordBuf to fit a record of at least the given length.
163-
* Returns true if successful, false if out of memory.
164156
*
165157
* readRecordBufSize is set to the new buffer size.
166158
*
@@ -172,7 +164,7 @@ XLogReaderFree(XLogReaderState *state)
172164
* Note: This routine should *never* be called for xl_tot_len until the header
173165
* of the record has been fully validated.
174166
*/
175-
staticbool
167+
staticvoid
176168
allocate_recordbuf(XLogReaderState*state,uint32reclength)
177169
{
178170
uint32newSize=reclength;
@@ -182,15 +174,8 @@ allocate_recordbuf(XLogReaderState *state, uint32 reclength)
182174

183175
if (state->readRecordBuf)
184176
pfree(state->readRecordBuf);
185-
state->readRecordBuf=
186-
(char*)palloc_extended(newSize,MCXT_ALLOC_NO_OOM);
187-
if (state->readRecordBuf==NULL)
188-
{
189-
state->readRecordBufSize=0;
190-
return false;
191-
}
177+
state->readRecordBuf= (char*)palloc(newSize);
192178
state->readRecordBufSize=newSize;
193-
return true;
194179
}
195180

196181
/*
@@ -523,14 +508,7 @@ XLogReadRecord(XLogReaderState *state, char **errormsg)
523508
Assert(gotlen <=lengthof(save_copy));
524509
Assert(gotlen <=state->readRecordBufSize);
525510
memcpy(save_copy,state->readRecordBuf,gotlen);
526-
if (!allocate_recordbuf(state,total_len))
527-
{
528-
/* We treat this as a "bogus data" condition */
529-
report_invalid_record(state,"record length %u at %X/%X too long",
530-
total_len,
531-
(uint32) (RecPtr >>32), (uint32)RecPtr);
532-
gotoerr;
533-
}
511+
allocate_recordbuf(state,total_len);
534512
memcpy(state->readRecordBuf,save_copy,gotlen);
535513
buffer=state->readRecordBuf+gotlen;
536514
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp