From 2a31b73a32982e67aff32f8b23d5f0916fd7485d Mon Sep 17 00:00:00 2001 From: Andrew Wood Date: Sat, 25 Apr 2026 22:04:38 +0100 Subject: [PATCH] Replace the fixed-sized buffers file_fdinfo and file_fdsymlink with dynamically allocated equivalents. --- src/include/pv-internal.h | 6 ++---- src/pv/watchpid.c | 44 ++++++++++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/include/pv-internal.h b/src/include/pv-internal.h index 1884d1c..80fc11e 100644 --- a/src/include/pv-internal.h +++ b/src/include/pv-internal.h @@ -48,8 +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_FDINFO 4096 -#define PV_SIZEOF_FILE_FDSYMLINK 4096 #define PV_SIZEOF_FILE_FDPATH 4096 #define PV_SIZEOF_DISPLAY_NAME 512 @@ -494,8 +492,8 @@ struct pvwatchfd_s { struct pvdisplay_s display; /* display data */ #ifdef __APPLE__ #else - char file_fdinfo[PV_SIZEOF_FILE_FDINFO]; /* path to /proc fdinfo file */ - char file_fdsymlink[PV_SIZEOF_FILE_FDSYMLINK]; /* path to /proc fd symlink */ + 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 */ /*@keep@ */ char display_name[PV_SIZEOF_DISPLAY_NAME]; /* name to show on progress bar */ diff --git a/src/pv/watchpid.c b/src/pv/watchpid.c index 71e052f..b45adb1 100644 --- a/src/pv/watchpid.c +++ b/src/pv/watchpid.c @@ -184,11 +184,32 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic) pv_perror("%s %u", _("pid"), info->watch_pid); return 1; } - (void) pv_snprintf(info->file_fdinfo, PV_SIZEOF_FILE_FDINFO, - "/proc/%u/fdinfo/%d", info->watch_pid, info->watch_fd); - (void) pv_snprintf(info->file_fdsymlink, PV_SIZEOF_FILE_FDSYMLINK, "/proc/%u/fd/%d", info->watch_pid, - info->watch_fd); + /* Build the string containing the path to the /proc fdinfo file. */ + if (NULL != info->file_fdinfo) { + free(info->file_fdinfo); + info->file_fdinfo = NULL; + } + if ((pv_asprintf(&(info->file_fdinfo), "/proc/%u/fdinfo/%d", info->watch_pid, info->watch_fd) < 0) + || (NULL == info->file_fdinfo)) { + if (!automatic) + pv_perror("%s %u", _("pid"), info->watch_pid); + return 2; + } + + /* Build the string containing the path to the /proc fd symlink. */ + if (NULL != info->file_fdsymlink) { + free(info->file_fdsymlink); + info->file_fdsymlink = NULL; + } + if ((pv_asprintf(&(info->file_fdsymlink), "/proc/%u/fd/%d", info->watch_pid, info->watch_fd) < 0) + || (NULL == info->file_fdsymlink)) { + if (!automatic) + pv_perror("%s %u", _("pid"), info->watch_pid); + return 2; + } + + /* 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 */ /* @@ -203,6 +224,7 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic) return 2; } + /* Run stat() on the /proc fd symlink and the path it points to. */ if (!((0 == stat(info->file_fdsymlink, &(info->sb_fd))) && (0 == lstat(info->file_fdsymlink, &(info->sb_fd_link))))) { if (!automatic) @@ -211,8 +233,8 @@ int pv_watchfd_info(pvstate_t state, pvwatchfd_t info, bool automatic) return 3; } + /* Find the size of the path pointed to. */ info->size = 0; - if (!filesize(info)) { if (!automatic) pv_error("%s %u: %s %d: %s: %s", @@ -242,6 +264,8 @@ bool pv_watchfd_changed(pvwatchfd_t info) if (NULL == info) return false; + if (NULL == info->file_fdsymlink) + return false; memset(&sb_fd, 0, sizeof(sb_fd)); memset(&sb_fd_link, 0, sizeof(sb_fd_link)); @@ -292,6 +316,8 @@ off_t pv_watchfd_position(pvwatchfd_t info) if (pv_watchfd_changed(info)) return -1; + if (NULL == info->file_fdinfo) + return -1; fptr = fopen(info->file_fdinfo, "r"); /* flawfinder: ignore */ /* flawfinder: trusted location (/proc). */ if (NULL == fptr) @@ -422,6 +448,14 @@ void pv_freecontents_watchfd(pvwatchfd_t info) pv_freecontents_calc(&(info->calc)); pv_freecontents_transfer(&(info->transfer)); pv_freecontents_display(&(info->display)); + if (NULL != info->file_fdinfo) { + free(info->file_fdinfo); + info->file_fdinfo = NULL; + } + if (NULL != info->file_fdsymlink) { + free(info->file_fdsymlink); + info->file_fdsymlink = NULL; + } }