Replace the fixed-sized buffer file_fdpath with a dynamically allocated equivalent.

This commit is contained in:
Andrew Wood
2026-04-29 21:43:46 +01:00
parent c54c3258a6
commit 79a6420fea
11 changed files with 171 additions and 109 deletions
+1 -2
View File
@@ -48,7 +48,6 @@ extern "C" {
#define PV_SIZEOF_PREVLINE_BUFFER 1024
#define PV_FORMAT_ARRAY_MAX 100
#define PV_SIZEOF_FORMAT_SEGMENTS_BUF 4096
#define PV_SIZEOF_FILE_FDPATH 4096
#define PV_SIZEOF_DISPLAY_NAME 512
#define PV_BARSTYLE_MAX 4 /* number of different styles allowed in a format */
@@ -498,7 +497,7 @@ struct pvwatchfd_s {
nullable_string_ptr file_fdinfo; /* path to /proc fdinfo file */
nullable_string_ptr file_fdsymlink; /* path to /proc fd symlink */
#endif
char file_fdpath[PV_SIZEOF_FILE_FDPATH]; /* path to file that was opened */
nullable_string_ptr file_fdpath; /* path to file that was opened */
/*@keep@ */ char display_name[PV_SIZEOF_DISPLAY_NAME]; /* name to show on progress bar */
struct stat sb_fd; /* stat of fd symlink */
struct stat sb_fd_link; /* lstat of fd symlink */
+5 -1
View File
@@ -221,7 +221,11 @@ pvstate_t pv_state_alloc(void)
for (try_size = 32; try_size <= 16384; try_size = try_size * 2) {
bool buffer_too_small;
/*@-mustfreeonly@ *//* splint mis-detects a memory leak here */
if (NULL != state->status.cwd) {
free(state->status.cwd);
state->status.cwd = NULL;
}
/*@-mustfreeonly@ *//* splint mis-detects this as a memory leak. */
state->status.cwd = malloc(try_size);
/*@+mustfreeonly@ */
if (NULL == state->status.cwd)
+61 -10
View File
@@ -44,6 +44,8 @@ static bool filesize(pvwatchfd_t info)
{
if (NULL == info)
return false;
if (NULL == info->file_fdpath)
return false;
if (S_ISBLK(info->sb_fd.st_mode)) {
int fd;
@@ -131,7 +133,15 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
return 3;
}
strlcpy(info->file_fdpath, vnodeInfo.pvip.vip_path, PV_SIZEOF_FILE_FDPATH);
if (NULL != info->file_fdpath) {
free(info->file_fdpath);
info->file_fdpath = NULL;
}
info->file_fdpath = pv_strdup(vnodeInfo.pvip.vip_path);
if (NULL == info->file_fdpath) {
pv_perror("%s %u: %s %d", _("pid"), info->watch_pid, _("fd"), info->watch_fd);
return 3;
}
info->size = 0;
@@ -210,15 +220,50 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic)
}
/* Get a string containing the path that the /proc fd symlink points to. */
memset(info->file_fdpath, 0, PV_SIZEOF_FILE_FDPATH);
if (readlink(info->file_fdsymlink, info->file_fdpath, PV_SIZEOF_FILE_FDPATH - 1) < 0) { /* flawfinder: ignore */
/*
* flawfinder: memset() has put \0 at the end already, and
* readlink() is given 1 byte less than the buffer length,
* so \0 termination is assured. See filesize() above for
* the mitigation of the risk that the link could change
* while it is being read.
*/
if (NULL != info->file_fdpath) {
free(info->file_fdpath);
info->file_fdpath = NULL;
}
/* Try buffers of different sizes - see readlink(2). */
{
size_t try_size;
for (try_size = 16; try_size <= 16384; try_size = try_size * 2) {
ssize_t bytes_stored;
if (NULL != info->file_fdpath) {
free(info->file_fdpath);
info->file_fdpath = NULL;
}
/*@-mustfreeonly@ *//* splint mis-detects this as a memory leak. */
info->file_fdpath = calloc(1, try_size);
/*@+mustfreeonly@ */
if (NULL == info->file_fdpath)
break;
bytes_stored = readlink(info->file_fdsymlink, info->file_fdpath, try_size - 1); /* flawfinder: ignore */
/*
* flawfinder: the risk is minimal, as no reads are
* performed.
*/
if (bytes_stored < 0) {
int old_errno;
old_errno = errno;
free(info->file_fdpath);
info->file_fdpath = NULL;
errno = old_errno;
break;
} else if (bytes_stored < (ssize_t) (try_size - 1)) {
info->file_fdpath[bytes_stored] = '\0';
break;
} else {
free(info->file_fdpath);
info->file_fdpath = NULL;
errno = ENAMETOOLONG;
}
}
}
if (NULL == info->file_fdpath) {
if (!automatic)
pv_perror("%s %u: %s %d", _("pid"), info->watch_pid, _("fd"), info->watch_fd);
return 2;
@@ -459,6 +504,10 @@ void pv_freecontents_watchfd(pvwatchfd_t info)
info->file_fdsymlink = NULL;
}
#endif
if (NULL != info->file_fdpath) {
free(info->file_fdpath);
info->file_fdpath = NULL;
}
}
@@ -725,6 +774,8 @@ void pv_watchpid_setname(pvstate_t state, pvwatchfd_t info)
file_fdpath = info->file_fdpath;
memset(info->display_name, 0, PV_SIZEOF_DISPLAY_NAME);
if (NULL == file_fdpath)
return;
path_length = strlen(info->file_fdpath); /* flawfinder: ignore */
cwd_length = 0;