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

Commit5c89684

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 parente81e8f9 commit5c89684

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
@@ -417,6 +417,7 @@ readfile(const char *path)
417417
intmaxlength=1,
418418
linelen=0;
419419
intnlines=0;
420+
intn;
420421
char**result;
421422
char*buffer;
422423
intc;
@@ -454,13 +455,13 @@ readfile(const char *path)
454455

455456
/* now reprocess the file and store the lines */
456457
rewind(infile);
457-
nlines=0;
458-
while (fgets(buffer,maxlength+1,infile)!=NULL)
459-
result[nlines++]=pg_strdup(buffer);
458+
n=0;
459+
while (fgets(buffer,maxlength+1,infile)!=NULL&&n<nlines)
460+
result[n++]=pg_strdup(buffer);
460461

461462
fclose(infile);
462463
free(buffer);
463-
result[nlines]=NULL;
464+
result[n]=NULL;
464465

465466
returnresult;
466467
}

‎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>
@@ -315,50 +316,77 @@ get_pgpid(void)
315316
staticchar**
316317
readfile(constchar*path)
317318
{
318-
FILE*infile;
319-
intmaxlength=1,
320-
linelen=0;
321-
intnlines=0;
319+
intfd;
320+
intnlines;
322321
char**result;
323322
char*buffer;
324-
intc;
323+
char*linebegin;
324+
inti;
325+
intn;
326+
intlen;
327+
structstatstatbuf;
325328

326-
if ((infile=fopen(path,"r"))==NULL)
329+
/*
330+
* Slurp the file into memory.
331+
*
332+
* The file can change concurrently, so we read the whole file into memory
333+
* with a single read() call. That's not guaranteed to get an atomic
334+
* snapshot, but in practice, for a small file, it's close enough for the
335+
* current use.
336+
*/
337+
fd=open(path,O_RDONLY |PG_BINARY,0);
338+
if (fd<0)
327339
returnNULL;
340+
if (fstat(fd,&statbuf)<0)
341+
returnNULL;
342+
if (statbuf.st_size==0)
343+
{
344+
/* empty file */
345+
result= (char**)pg_malloc(sizeof(char*));
346+
*result=NULL;
347+
returnresult;
348+
}
349+
buffer=pg_malloc(statbuf.st_size+1);
328350

329-
/* pass over the file twice - the first time to size the result */
351+
len=read(fd,buffer,statbuf.st_size+1);
352+
close(fd);
353+
if (len!=statbuf.st_size)
354+
{
355+
/* oops, the file size changed between fstat and read */
356+
free(buffer);
357+
returnNULL;
358+
}
330359

331-
while ((c=fgetc(infile))!=EOF)
360+
/* count newlines */
361+
nlines=0;
362+
for (i=0;i<len-1;i++)
332363
{
333-
linelen++;
334-
if (c=='\n')
335-
{
364+
if (buffer[i]=='\n')
336365
nlines++;
337-
if (linelen>maxlength)
338-
maxlength=linelen;
339-
linelen=0;
340-
}
341366
}
367+
nlines++;/* account for the last line */
342368

343-
/* handle last line without a terminating newline (yuck) */
344-
if (linelen)
345-
nlines++;
346-
if (linelen>maxlength)
347-
maxlength=linelen;
348-
349-
/* set up the result and the line buffer */
369+
/* set up the result buffer */
350370
result= (char**)pg_malloc((nlines+1)*sizeof(char*));
351-
buffer= (char*)pg_malloc(maxlength+1);
352371

353-
/* now reprocess the file and store the lines */
354-
rewind(infile);
355-
nlines=0;
356-
while (fgets(buffer,maxlength+1,infile)!=NULL)
357-
result[nlines++]=pg_strdup(buffer);
372+
/* now split the buffer into lines */
373+
linebegin=buffer;
374+
n=0;
375+
for (i=0;i<len;i++)
376+
{
377+
if (buffer[i]=='\n'||i==len-1)
378+
{
379+
intslen=&buffer[i]-linebegin+1;
380+
char*linebuf=pg_malloc(slen+1);
381+
memcpy(linebuf,linebegin,slen);
382+
linebuf[slen]='\0';
383+
result[n++]=linebuf;
384+
linebegin=&buffer[i+1];
385+
}
386+
}
387+
result[n]=NULL;
358388

359-
fclose(infile);
360389
free(buffer);
361-
result[nlines]=NULL;
362390

363391
returnresult;
364392
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp