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

Commit5403747

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 parent4d4005c commit5403747

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
@@ -408,6 +408,7 @@ readfile(const char *path)
408408
intmaxlength=1,
409409
linelen=0;
410410
intnlines=0;
411+
intn;
411412
char**result;
412413
char*buffer;
413414
intc;
@@ -445,13 +446,13 @@ readfile(const char *path)
445446

446447
/* now reprocess the file and store the lines */
447448
rewind(infile);
448-
nlines=0;
449-
while (fgets(buffer,maxlength+1,infile)!=NULL)
450-
result[nlines++]=xstrdup(buffer);
449+
n=0;
450+
while (fgets(buffer,maxlength+1,infile)!=NULL&&n<nlines)
451+
result[n++]=xstrdup(buffer);
451452

452453
fclose(infile);
453454
free(buffer);
454-
result[nlines]=NULL;
455+
result[n]=NULL;
455456

456457
returnresult;
457458
}

‎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>
@@ -310,50 +311,77 @@ get_pgpid(void)
310311
staticchar**
311312
readfile(constchar*path)
312313
{
313-
FILE*infile;
314-
intmaxlength=1,
315-
linelen=0;
316-
intnlines=0;
314+
intfd;
315+
intnlines;
317316
char**result;
318317
char*buffer;
319-
intc;
318+
char*linebegin;
319+
inti;
320+
intn;
321+
intlen;
322+
structstatstatbuf;
320323

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

324-
/* pass over the file twice - the first time to size the result */
346+
len=read(fd,buffer,statbuf.st_size+1);
347+
close(fd);
348+
if (len!=statbuf.st_size)
349+
{
350+
/* oops, the file size changed between fstat and read */
351+
free(buffer);
352+
returnNULL;
353+
}
325354

326-
while ((c=fgetc(infile))!=EOF)
355+
/* count newlines */
356+
nlines=0;
357+
for (i=0;i<len-1;i++)
327358
{
328-
linelen++;
329-
if (c=='\n')
330-
{
359+
if (buffer[i]=='\n')
331360
nlines++;
332-
if (linelen>maxlength)
333-
maxlength=linelen;
334-
linelen=0;
335-
}
336361
}
362+
nlines++;/* account for the last line */
337363

338-
/* handle last line without a terminating newline (yuck) */
339-
if (linelen)
340-
nlines++;
341-
if (linelen>maxlength)
342-
maxlength=linelen;
343-
344-
/* set up the result and the line buffer */
364+
/* set up the result buffer */
345365
result= (char**)pg_malloc((nlines+1)*sizeof(char*));
346-
buffer= (char*)pg_malloc(maxlength+1);
347366

348-
/* now reprocess the file and store the lines */
349-
rewind(infile);
350-
nlines=0;
351-
while (fgets(buffer,maxlength+1,infile)!=NULL)
352-
result[nlines++]=xstrdup(buffer);
367+
/* now split the buffer into lines */
368+
linebegin=buffer;
369+
n=0;
370+
for (i=0;i<len;i++)
371+
{
372+
if (buffer[i]=='\n'||i==len-1)
373+
{
374+
intslen=&buffer[i]-linebegin+1;
375+
char*linebuf=pg_malloc(slen+1);
376+
memcpy(linebuf,linebegin,slen);
377+
linebuf[slen]='\0';
378+
result[n++]=linebuf;
379+
linebegin=&buffer[i+1];
380+
}
381+
}
382+
result[n]=NULL;
353383

354-
fclose(infile);
355384
free(buffer);
356-
result[nlines]=NULL;
357385

358386
returnresult;
359387
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp