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

Commit2883674

Browse files
committed
Fix race condition in pg_ctl reading postmaster.pid.
If postmaster changed postmaster.pid while pg_ctl was reading it, pg_ctlcould overrun the buffer it allocated for the file. Fix by reading thewhole file to memory with one read() call.initdb contains an identical copy of the readfile() function, but the filesthat initdb reads are static, not modified concurrently. Nevertheless, adda simple bounds-check there, if only to silence static analysis tools.Per report from Dave Vitek. Backpatch to all supported branches.
1 parenteb5e0d8 commit2883674

File tree

2 files changed

+63
-34
lines changed

2 files changed

+63
-34
lines changed

‎src/bin/initdb/initdb.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ readfile(const char *path)
373373
intmaxlength=1,
374374
linelen=0;
375375
intnlines=0;
376+
intn;
376377
char**result;
377378
char*buffer;
378379
intc;
@@ -410,13 +411,13 @@ readfile(const char *path)
410411

411412
/* now reprocess the file and store the lines */
412413
rewind(infile);
413-
nlines=0;
414-
while (fgets(buffer,maxlength+1,infile)!=NULL)
415-
result[nlines++]=xstrdup(buffer);
414+
n=0;
415+
while (fgets(buffer,maxlength+1,infile)!=NULL&&n<nlines)
416+
result[n++]=xstrdup(buffer);
416417

417418
fclose(infile);
418419
free(buffer);
419-
result[nlines]=NULL;
420+
result[n]=NULL;
420421

421422
returnresult;
422423
}

‎src/bin/pg_ctl/pg_ctl.c

Lines changed: 58 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include"postgres_fe.h"
2121
#include"libpq-fe.h"
2222

23+
#include<fcntl.h>
2324
#include<locale.h>
2425
#include<signal.h>
2526
#include<time.h>
@@ -305,50 +306,77 @@ get_pgpid(void)
305306
staticchar**
306307
readfile(constchar*path)
307308
{
308-
FILE*infile;
309-
intmaxlength=1,
310-
linelen=0;
311-
intnlines=0;
309+
intfd;
310+
intnlines;
312311
char**result;
313312
char*buffer;
314-
intc;
313+
char*linebegin;
314+
inti;
315+
intn;
316+
intlen;
317+
structstatstatbuf;
315318

316-
if ((infile=fopen(path,"r"))==NULL)
319+
/*
320+
* Slurp the file into memory.
321+
*
322+
* The file can change concurrently, so we read the whole file into memory
323+
* with a single read() call. That's not guaranteed to get an atomic
324+
* snapshot, but in practice, for a small file, it's close enough for the
325+
* current use.
326+
*/
327+
fd=open(path,O_RDONLY |PG_BINARY,0);
328+
if (fd<0)
317329
returnNULL;
330+
if (fstat(fd,&statbuf)<0)
331+
returnNULL;
332+
if (statbuf.st_size==0)
333+
{
334+
/* empty file */
335+
result= (char**)pg_malloc(sizeof(char*));
336+
*result=NULL;
337+
returnresult;
338+
}
339+
buffer=pg_malloc(statbuf.st_size+1);
318340

319-
/* pass over the file twice - the first time to size the result */
341+
len=read(fd,buffer,statbuf.st_size+1);
342+
close(fd);
343+
if (len!=statbuf.st_size)
344+
{
345+
/* oops, the file size changed between fstat and read */
346+
free(buffer);
347+
returnNULL;
348+
}
320349

321-
while ((c=fgetc(infile))!=EOF)
350+
/* count newlines */
351+
nlines=0;
352+
for (i=0;i<len-1;i++)
322353
{
323-
linelen++;
324-
if (c=='\n')
325-
{
354+
if (buffer[i]=='\n')
326355
nlines++;
327-
if (linelen>maxlength)
328-
maxlength=linelen;
329-
linelen=0;
330-
}
331356
}
357+
nlines++;/* account for the last line */
332358

333-
/* handle last line without a terminating newline (yuck) */
334-
if (linelen)
335-
nlines++;
336-
if (linelen>maxlength)
337-
maxlength=linelen;
338-
339-
/* set up the result and the line buffer */
359+
/* set up the result buffer */
340360
result= (char**)pg_malloc((nlines+1)*sizeof(char*));
341-
buffer= (char*)pg_malloc(maxlength+1);
342361

343-
/* now reprocess the file and store the lines */
344-
rewind(infile);
345-
nlines=0;
346-
while (fgets(buffer,maxlength+1,infile)!=NULL)
347-
result[nlines++]=xstrdup(buffer);
362+
/* now split the buffer into lines */
363+
linebegin=buffer;
364+
n=0;
365+
for (i=0;i<len;i++)
366+
{
367+
if (buffer[i]=='\n'||i==len-1)
368+
{
369+
intslen=&buffer[i]-linebegin+1;
370+
char*linebuf=pg_malloc(slen+1);
371+
memcpy(linebuf,linebegin,slen);
372+
linebuf[slen]='\0';
373+
result[n++]=linebuf;
374+
linebegin=&buffer[i+1];
375+
}
376+
}
377+
result[n]=NULL;
348378

349-
fclose(infile);
350379
free(buffer);
351-
result[nlines]=NULL;
352380

353381
returnresult;
354382
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp