Skip to content

Commit c67f366

Browse files
committed
Fix multiple bugs and infelicities in pg_rewind.
Bugs all spotted by Coverity, including wrong realloc() size request and memory leaks. Cosmetic improvements by me. The usage of the global variable "filemap" here is still pretty awful, but at least I got rid of the gratuitous aliasing in several routines (which was helping to annoy Coverity, as well as being a bug risk).
1 parent e4cbfd6 commit c67f366

File tree

4 files changed

+46
-44
lines changed

4 files changed

+46
-44
lines changed

src/bin/pg_rewind/filemap.c

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ static char *datasegpath(RelFileNode rnode, ForkNumber forknum,
3030
BlockNumber segno);
3131
static int path_cmp(const void *a, const void *b);
3232
static int final_filemap_cmp(const void *a, const void *b);
33-
static void filemap_list_to_array(void);
33+
static void filemap_list_to_array(filemap_t *map);
3434

3535
/*
36-
* Create a new file map.
36+
* Create a new file map (stored in the global pointer "filemap").
3737
*/
38-
filemap_t *
38+
void
3939
filemap_create(void)
4040
{
4141
filemap_t *map;
@@ -48,8 +48,6 @@ filemap_create(void)
4848

4949
Assert(filemap == NULL);
5050
filemap = map;
51-
52-
return map;
5351
}
5452

5553
/*
@@ -271,7 +269,10 @@ process_local_file(const char *path, file_type_t type, size_t oldsize,
271269
pg_fatal("remote file list is empty\n");
272270
}
273271

274-
filemap_list_to_array();
272+
filemap_list_to_array(map);
273+
274+
Assert(map->array != NULL);
275+
275276
qsort(map->array, map->narray, sizeof(file_entry_t *), path_cmp);
276277
}
277278

@@ -284,8 +285,8 @@ process_local_file(const char *path, file_type_t type, size_t oldsize,
284285

285286
key.path = (char *) path;
286287
key_ptr = &key;
287-
exists = bsearch(&key_ptr, map->array, map->narray, sizeof(file_entry_t *),
288-
path_cmp) != NULL;
288+
exists = (bsearch(&key_ptr, map->array, map->narray, sizeof(file_entry_t *),
289+
path_cmp) != NULL);
289290

290291
/* Remove any file or folder that doesn't exist in the remote system. */
291292
if (!exists)
@@ -335,7 +336,7 @@ process_block_change(ForkNumber forknum, RelFileNode rnode, BlockNumber blkno)
335336
filemap_t *map = filemap;
336337
file_entry_t **e;
337338

338-
Assert(filemap->array);
339+
Assert(map->array);
339340

340341
segno = blkno / RELSEG_SIZE;
341342
blkno_inseg = blkno % RELSEG_SIZE;
@@ -395,38 +396,40 @@ process_block_change(ForkNumber forknum, RelFileNode rnode, BlockNumber blkno)
395396
}
396397

397398
/*
398-
* Convert the linked list of entries in filemap->first/last to the array,
399-
* filemap->array.
399+
* Convert the linked list of entries in map->first/last to the array,
400+
* map->array.
400401
*/
401402
static void
402-
filemap_list_to_array(void)
403+
filemap_list_to_array(filemap_t *map)
403404
{
404405
int narray;
405406
file_entry_t *entry,
406407
*next;
407408

408-
filemap->array =
409-
pg_realloc(filemap->array,
410-
(filemap->nlist + filemap->narray) * sizeof(file_entry_t));
409+
map->array = (file_entry_t **)
410+
pg_realloc(map->array,
411+
(map->nlist + map->narray) * sizeof(file_entry_t *));
411412

412-
narray = filemap->narray;
413-
for (entry = filemap->first; entry != NULL; entry = next)
413+
narray = map->narray;
414+
for (entry = map->first; entry != NULL; entry = next)
414415
{
415-
filemap->array[narray++] = entry;
416+
map->array[narray++] = entry;
416417
next = entry->next;
417418
entry->next = NULL;
418419
}
419-
Assert(narray == filemap->nlist + filemap->narray);
420-
filemap->narray = narray;
421-
filemap->nlist = 0;
422-
filemap->first = filemap->last = NULL;
420+
Assert(narray == map->nlist + map->narray);
421+
map->narray = narray;
422+
map->nlist = 0;
423+
map->first = map->last = NULL;
423424
}
424425

425426
void
426427
filemap_finalize(void)
427428
{
428-
filemap_list_to_array();
429-
qsort(filemap->array, filemap->narray, sizeof(file_entry_t *),
429+
filemap_t *map = filemap;
430+
431+
filemap_list_to_array(map);
432+
qsort(map->array, map->narray, sizeof(file_entry_t *),
430433
final_filemap_cmp);
431434
}
432435

@@ -466,9 +469,9 @@ calculate_totals(void)
466469
map->total_size = 0;
467470
map->fetch_size = 0;
468471

469-
for (i = 0; i < filemap->narray; i++)
472+
for (i = 0; i < map->narray; i++)
470473
{
471-
entry = filemap->array[i];
474+
entry = map->array[i];
472475

473476
if (entry->type != FILE_TYPE_REGULAR)
474477
continue;
@@ -501,12 +504,13 @@ calculate_totals(void)
501504
void
502505
print_filemap(void)
503506
{
507+
filemap_t *map = filemap;
504508
file_entry_t *entry;
505509
int i;
506510

507-
for (i = 0; i < filemap->narray; i++)
511+
for (i = 0; i < map->narray; i++)
508512
{
509-
entry = filemap->array[i];
513+
entry = map->array[i];
510514
if (entry->action != FILE_ACTION_NONE ||
511515
entry->pagemap.bitmapsize > 0)
512516
{

src/bin/pg_rewind/filemap.h

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ typedef enum
2929
FILE_ACTION_NONE, /* no action (we might still copy modified blocks
3030
* based on the parsed WAL) */
3131
FILE_ACTION_TRUNCATE, /* truncate local file to 'newsize' bytes */
32-
FILE_ACTION_REMOVE, /* remove local file / directory / symlink */
33-
32+
FILE_ACTION_REMOVE /* remove local file / directory / symlink */
3433
} file_action_t;
3534

3635
typedef enum
@@ -40,7 +39,7 @@ typedef enum
4039
FILE_TYPE_SYMLINK
4140
} file_type_t;
4241

43-
struct file_entry_t
42+
typedef struct file_entry_t
4443
{
4544
char *path;
4645
file_type_t type;
@@ -58,19 +57,17 @@ struct file_entry_t
5857
char *link_target;
5958

6059
struct file_entry_t *next;
61-
};
62-
63-
typedef struct file_entry_t file_entry_t;
60+
} file_entry_t;
6461

65-
struct filemap_t
62+
typedef struct filemap_t
6663
{
6764
/*
6865
* New entries are accumulated to a linked list, in process_remote_file
6966
* and process_local_file.
7067
*/
7168
file_entry_t *first;
7269
file_entry_t *last;
73-
int nlist;
70+
int nlist; /* number of entries currently in list */
7471

7572
/*
7673
* After processing all the remote files, the entries in the linked list
@@ -80,22 +77,19 @@ struct filemap_t
8077
* the array, and the linked list is empty.
8178
*/
8279
file_entry_t **array;
83-
int narray;
80+
int narray; /* current length of array */
8481

8582
/*
8683
* Summary information. total_size is the total size of the source cluster,
8784
* and fetch_size is the number of bytes that needs to be copied.
8885
*/
8986
uint64 total_size;
9087
uint64 fetch_size;
91-
};
92-
93-
typedef struct filemap_t filemap_t;
94-
95-
extern filemap_t * filemap;
88+
} filemap_t;
9689

97-
extern filemap_t *filemap_create(void);
90+
extern filemap_t *filemap;
9891

92+
extern void filemap_create(void);
9993
extern void calculate_totals(void);
10094
extern void print_filemap(void);
10195

src/bin/pg_rewind/libpq_fetch.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,10 @@ receiveFileChunks(const char *sql)
285285
open_target_file(filename, false);
286286

287287
write_target_range(chunk, chunkoff, chunksize);
288+
289+
pg_free(filename);
290+
291+
PQclear(res);
288292
}
289293
}
290294

src/bin/pg_rewind/pg_rewind.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ main(int argc, char **argv)
248248
/*
249249
* Build the filemap, by comparing the remote and local data directories.
250250
*/
251-
(void) filemap_create();
251+
filemap_create();
252252
pg_log(PG_PROGRESS, "reading source file list\n");
253253
fetchRemoteFileList();
254254
pg_log(PG_PROGRESS, "reading target file list\n");

0 commit comments

Comments
 (0)