Some fields can exceed size limit, e.g. private data has no size restriction. Therefore it needs to be dynamically increased.
Change-Id: Ie274fd304eba5d600e198f4febbc6216f01b57e1 --- src/topology/save.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-)
diff --git a/src/topology/save.c b/src/topology/save.c index 4ecf86c..9c74735 100644 --- a/src/topology/save.c +++ b/src/topology/save.c @@ -19,22 +19,43 @@ #include "tplg_local.h"
#define SAVE_ALLOC_SHIFT (13) /* 8192 bytes */ +#define PRINT_BUF_SIZE (1024) +#define PRINT_BUF_SIZE_MAX (1024 * 1024)
int tplg_save_printf(char **dst, const char *pfx, const char *fmt, ...) { va_list va; - char buf[1024], *s; + char *buf, *s; size_t n, l, t, pl; + int ret = 0; + + buf = malloc(PRINT_BUF_SIZE); + if (!buf) + return -ENOMEM;
if (pfx == NULL) pfx = "";
va_start(va, fmt); - n = vsnprintf(buf, sizeof(buf), fmt, va); + n = vsnprintf(buf, PRINT_BUF_SIZE, fmt, va); va_end(va);
- if (n >= sizeof(buf)) - return -EOVERFLOW; + if (n >= PRINT_BUF_SIZE_MAX) { + ret = -EOVERFLOW; + goto end; + } + + if (n >= PRINT_BUF_SIZE) { + char *tmp = realloc(buf, n + 1); + if (!tmp) { + ret = -ENOMEM; + goto end; + } + buf = tmp; + va_start(va, fmt); + n = vsnprintf(buf, n + 1, fmt, va); + va_end(va); + }
pl = strlen(pfx); l = *dst ? strlen(*dst) : 0; @@ -47,7 +68,8 @@ int tplg_save_printf(char **dst, const char *pfx, const char *fmt, ...) if (s == NULL) { free(*dst); *dst = NULL; - return -ENOMEM; + ret = -ENOMEM; + goto end; } } else { s = *dst; @@ -57,6 +79,8 @@ int tplg_save_printf(char **dst, const char *pfx, const char *fmt, ...) strcpy(s + l, pfx); strcpy(s + l + pl, buf); *dst = s; +end: + free(buf); return 0; }