From dbe20d453d5e93bd0f1188a8851c6cf4fd230b26 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Sat, 11 Nov 2023 00:01:34 -0500 Subject: Extend path_append_ex to truncate compname, remove some strmemdupa remove some duplicated strings previously allocd off the stack just removing string duplications that are easily handled with truncation now available with path_append_ex() this also has an advantage of less stack used in worst case scenarios Change-Id: I3a43e33ef8a8c36599e4c6c036a0ccdd8ed0c883 --- firmware/common/pathfuncs.c | 69 +++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 21 deletions(-) (limited to 'firmware/common/pathfuncs.c') diff --git a/firmware/common/pathfuncs.c b/firmware/common/pathfuncs.c index ff3de7b616..0fbac68221 100644 --- a/firmware/common/pathfuncs.c +++ b/firmware/common/pathfuncs.c @@ -447,10 +447,22 @@ void path_remove_dot_segments (char *dstpath, const char *path) *dstp = 0; } +/* helper function copy n chars of a string to a dst buffer of dst_sz + * returns the length of the string it created or attempted to create + */ +static inline size_t copynchars(char *dst, size_t dst_sz, const char *src, size_t src_max) +{ + int cpychrs = -1; + if (src_max < -1u) /* we could be dealing with unterminated strings */ + cpychrs = src_max; + /* testing shows this to be on par with using discreet functions and safer ;) */ + int ret = snprintf(dst, dst_sz, "%.*s", cpychrs, src); + if (ret >= 0) + return ret; + + return 0; /* Error */ +} /* Appends one path to another, adding separators between components if needed. - * basepath_max can be used to truncate the basepath if desired - * NOTE: basepath is truncated after copying to the buffer so there must be enough - * free space for the entirety of the basepath even if the resulting string would fit * * Return value and behavior is otherwise as strlcpy so that truncation may be * detected. @@ -458,45 +470,52 @@ void path_remove_dot_segments (char *dstpath, const char *path) * For basepath and component: * PA_SEP_HARD adds a separator even if the base path is empty * PA_SEP_SOFT adds a separator only if the base path is not empty + * + * basepath_max can be used to truncate the basepath if desired + * component_max can be used to truncate the component if desired + * + * (Supply -1u to disable truncation) */ size_t path_append_ex(char *buf, const char *basepath, size_t basepath_max, - const char *component, size_t bufsize) + const char *component, size_t component_max, size_t bufsize) { size_t len; + bool check_base = (basepath_max == 0); bool separate = false; - const char *base = basepath && basepath[0] ? basepath : buf; + const char *base = basepath && !check_base && basepath[0] ? basepath : buf; + if (!base) return bufsize; /* won't work to get lengths from buf */ if (!buf) + { + static char fbuf; /* fake buffer to elide later null checks */ + buf = &fbuf; bufsize = 0; - + } + if (!component) + { + check_base = true; + component = ""; + } if (path_is_absolute(component)) { /* 'component' is absolute; replace all */ basepath = component; + basepath_max = component_max; component = ""; - basepath_max = -1u; } /* if basepath is not null or empty, buffer contents are replaced, otherwise buf contains the base path */ - if (base == buf) len = strlen(buf); else - { - len = strlcpy(buf, basepath, bufsize); - if (basepath_max < len) - { - len = basepath_max; - buf[basepath_max] = '\0'; - } - } + len = copynchars(buf, bufsize, basepath, basepath_max); - if (!basepath || !component || basepath_max == 0) + if (!basepath || basepath_max == 0 || check_base) separate = !len || base[len-1] != PATH_SEPCH; - else if (component[0]) + else if (component[0] && component_max > 0) separate = len && base[len-1] != PATH_SEPCH; /* caller might lie about size of buf yet use buf as the base */ @@ -509,14 +528,22 @@ size_t path_append_ex(char *buf, const char *basepath, size_t basepath_max, if (separate && (len++, bufsize > 0) && --bufsize > 0) *buf++ = PATH_SEPCH; - return len + strlcpy(buf, component ?: "", bufsize); + return len + copynchars(buf, bufsize, component, component_max); } - +/* Appends one path to another, adding separators between components if needed. + * + * Return value and behavior is otherwise as strlcpy so that truncation may be + * detected. + * + * For basepath and component: + * PA_SEP_HARD adds a separator even if the base path is empty + * PA_SEP_SOFT adds a separator only if the base path is not empty + */ size_t path_append(char *buf, const char *basepath, const char *component, size_t bufsize) { - return path_append_ex(buf, basepath, -1u, component, bufsize); + return path_append_ex(buf, basepath, -1u, component, -1u, bufsize); } /* Returns the location and length of the next path component, consuming the * input in the process. -- cgit v1.2.3