diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index f21407c507..ad6767e92f 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.236 2006/04/17 18:55:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.237 2006/04/20 04:07:38 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -2727,7 +2727,25 @@ ReadRecord(XLogRecPtr *RecPtr, int emode) readFile = XLogFileRead(readId, readSeg, emode); if (readFile < 0) goto next_record_is_invalid; - readOff = (uint32) (-1); /* force read to occur below */ + + /* + * Whenever switching to a new WAL segment, we read the first page of + * the file and validate its header, even if that's not where the + * target record is. This is so that we can check the additional + * identification info that is present in the first page's "long" + * header. + */ + readOff = 0; + if (read(readFile, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ) + { + ereport(emode, + (errcode_for_file_access(), + errmsg("could not read from log file %u, segment %u, offset %u: %m", + readId, readSeg, readOff))); + goto next_record_is_invalid; + } + if (!ValidXLOGHeader((XLogPageHeader) readBuf, emode)) + goto next_record_is_invalid; } targetPageOff = ((RecPtr->xrecoff % XLogSegSize) / XLOG_BLCKSZ) * XLOG_BLCKSZ; @@ -3036,6 +3054,15 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode) return false; } } + else if (readOff == 0) + { + /* hmm, first page of file doesn't have a long header? */ + ereport(emode, + (errmsg("invalid info bits %04X in log file %u, segment %u, offset %u", + hdr->xlp_info, readId, readSeg, readOff))); + return false; + } + recaddr.xlogid = readId; recaddr.xrecoff = readSeg * XLogSegSize + readOff; if (!XLByteEQ(hdr->xlp_pageaddr, recaddr))