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

Commit1c95b5e

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 parent5c07de4 commit1c95b5e

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
@@ -368,6 +368,7 @@ readfile(const char *path)
368368
intmaxlength=1,
369369
linelen=0;
370370
intnlines=0;
371+
intn;
371372
char**result;
372373
char*buffer;
373374
intc;
@@ -405,13 +406,13 @@ readfile(const char *path)
405406

406407
/* now reprocess the file and store the lines */
407408
rewind(infile);
408-
nlines=0;
409-
while (fgets(buffer,maxlength+1,infile)!=NULL)
410-
result[nlines++]=xstrdup(buffer);
409+
n=0;
410+
while (fgets(buffer,maxlength+1,infile)!=NULL&&n<nlines)
411+
result[n++]=xstrdup(buffer);
411412

412413
fclose(infile);
413414
free(buffer);
414-
result[nlines]=NULL;
415+
result[n]=NULL;
415416

416417
returnresult;
417418
}

‎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<sys/types.h>
@@ -297,50 +298,77 @@ get_pgpid(void)
297298
staticchar**
298299
readfile(constchar*path)
299300
{
300-
FILE*infile;
301-
intmaxlength=1,
302-
linelen=0;
303-
intnlines=0;
301+
intfd;
302+
intnlines;
304303
char**result;
305304
char*buffer;
306-
intc;
305+
char*linebegin;
306+
inti;
307+
intn;
308+
intlen;
309+
structstatstatbuf;
307310

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

311-
/* pass over the file twice - the first time to size the result */
333+
len=read(fd,buffer,statbuf.st_size+1);
334+
close(fd);
335+
if (len!=statbuf.st_size)
336+
{
337+
/* oops, the file size changed between fstat and read */
338+
free(buffer);
339+
returnNULL;
340+
}
312341

313-
while ((c=fgetc(infile))!=EOF)
342+
/* count newlines */
343+
nlines=0;
344+
for (i=0;i<len-1;i++)
314345
{
315-
linelen++;
316-
if (c=='\n')
317-
{
346+
if (buffer[i]=='\n')
318347
nlines++;
319-
if (linelen>maxlength)
320-
maxlength=linelen;
321-
linelen=0;
322-
}
323348
}
349+
nlines++;/* account for the last line */
324350

325-
/* handle last line without a terminating newline (yuck) */
326-
if (linelen)
327-
nlines++;
328-
if (linelen>maxlength)
329-
maxlength=linelen;
330-
331-
/* set up the result and the line buffer */
351+
/* set up the result buffer */
332352
result= (char**)pg_malloc((nlines+1)*sizeof(char*));
333-
buffer= (char*)pg_malloc(maxlength+1);
334353

335-
/* now reprocess the file and store the lines */
336-
rewind(infile);
337-
nlines=0;
338-
while (fgets(buffer,maxlength+1,infile)!=NULL)
339-
result[nlines++]=xstrdup(buffer);
354+
/* now split the buffer into lines */
355+
linebegin=buffer;
356+
n=0;
357+
for (i=0;i<len;i++)
358+
{
359+
if (buffer[i]=='\n'||i==len-1)
360+
{
361+
intslen=&buffer[i]-linebegin+1;
362+
char*linebuf=pg_malloc(slen+1);
363+
memcpy(linebuf,linebegin,slen);
364+
linebuf[slen]='\0';
365+
result[n++]=linebuf;
366+
linebegin=&buffer[i+1];
367+
}
368+
}
369+
result[n]=NULL;
340370

341-
fclose(infile);
342371
free(buffer);
343-
result[nlines]=NULL;
344372

345373
returnresult;
346374
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp