From 5546a8746558d088d90ba8f6cb52a50f886c9572 Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Fri, 22 May 2026 15:46:37 +0200 Subject: out-limd: Properly handle snprintf and some smaller improvements --- src/out-limd.c | 111 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 84 insertions(+), 27 deletions(-) diff --git a/src/out-limd.c b/src/out-limd.c index 8d42c9d..6d864cb 100644 --- a/src/out-limd.c +++ b/src/out-limd.c @@ -46,17 +46,27 @@ static size_t dtostr(char *buf, size_t bufsize, double realval) { - size_t len = 0; + int slen = 0; if (isnan(realval)) { - len = snprintf(buf, bufsize, "nan"); + slen = snprintf(buf, bufsize, "nan"); } else if (isinf(realval)) { - len = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-'); + slen = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-'); } else if (realval == 0.0f) { - len = snprintf(buf, bufsize, "0.0"); + slen = snprintf(buf, bufsize, "0.0"); } else { + slen = snprintf(buf, bufsize, "%.*g", 17, realval); + if (slen < 0) { + return 0; + } + if (!buf || bufsize == 0) { + return (size_t)slen; + } + size_t len = (size_t)slen; + if (len >= bufsize) { + len = bufsize - 1; + } size_t i = 0; - len = snprintf(buf, bufsize, "%.*g", 17, realval); - for (i = 0; buf && i < len; i++) { + for (i = 0; i < len; i++) { if (buf[i] == ',') { buf[i] = '.'; break; @@ -64,8 +74,12 @@ static size_t dtostr(char *buf, size_t bufsize, double realval) break; } } + return len; + } + if (slen < 0) { + return 0; } - return len; + return (size_t)slen; } static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t depth, uint32_t indent) @@ -73,15 +87,20 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de plist_data_t node_data = NULL; char *val = NULL; + int slen = 0; size_t val_len = 0; char buf[16]; uint32_t i = 0; - if (!node) + if (!node || !outbuf || !*outbuf) { return PLIST_ERR_INVALID_ARG; + } node_data = plist_get_data(node); + if (!node_data) { + return PLIST_ERR_INVALID_ARG; + } switch (node_data->type) { @@ -92,26 +111,37 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de } else { str_buf_append(*outbuf, "false", 5); } + break; } - break; case PLIST_NULL: str_buf_append(*outbuf, "null", 4); - break; + break; case PLIST_INT: val = (char*)malloc(64); + if (!val) { + return PLIST_ERR_NO_MEM; + } if (node_data->length == 16) { - val_len = snprintf(val, 64, "%" PRIu64, node_data->intval); + slen = snprintf(val, 64, "%" PRIu64, node_data->intval); } else { - val_len = snprintf(val, 64, "%" PRIi64, node_data->intval); + slen = snprintf(val, 64, "%" PRIi64, node_data->intval); + } + if (slen < 0) { + free(val); + return PLIST_ERR_UNKNOWN; } + val_len = (size_t)slen; str_buf_append(*outbuf, val, val_len); free(val); break; case PLIST_REAL: val = (char*)malloc(64); + if (!val) { + return PLIST_ERR_NO_MEM; + } val_len = dtostr(val, 64, node_data->realval); str_buf_append(*outbuf, val, val_len); free(val); @@ -119,18 +149,21 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de case PLIST_STRING: case PLIST_KEY: { + if (!node_data->strval && node_data->length > 0) { + return PLIST_ERR_INVALID_ARG; + } const char *charmap[32] = { "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\u000b", "\\f", "\\r", "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f", }; + size_t j = 0; - size_t len = 0; - off_t start = 0; - off_t cur = 0; + size_t len = node_data->length; + size_t start = 0; + size_t cur = 0; - len = node_data->length; for (j = 0; j < len; j++) { unsigned char ch = (unsigned char)node_data->strval[j]; if (ch < 0x20) { @@ -138,11 +171,12 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de str_buf_append(*outbuf, charmap[ch], (charmap[ch][1] == 'u') ? 6 : 2); start = cur+1; } + cur++; } str_buf_append(*outbuf, node_data->strval + start, cur - start); - } break; - + break; + } case PLIST_ARRAY: { node_t ch; uint32_t cnt = 0; @@ -153,15 +187,19 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de str_buf_append(*outbuf, " ", 1); } } - size_t sl = sprintf(buf, "%u: ", cnt); - str_buf_append(*outbuf, buf, sl); + slen = snprintf(buf, sizeof(buf), "%u: ", cnt); + if (slen < 0) { + return PLIST_ERR_UNKNOWN; + } + str_buf_append(*outbuf, buf, (size_t)slen); plist_err_t res = node_to_string(ch, outbuf, depth+1, indent); if (res < 0) { return res; } cnt++; } - } break; + break; + } case PLIST_DICT: { node_t ch; uint32_t cnt = 0; @@ -179,17 +217,27 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de if (cnt % 2 == 0) { plist_t valnode = (plist_t)node_next_sibling(ch); if (PLIST_IS_ARRAY(valnode)) { - size_t sl = sprintf(buf, "[%u]:", plist_array_get_size(valnode)); - str_buf_append(*outbuf, buf, sl); + slen = snprintf(buf, sizeof(buf), "[%u]:", plist_array_get_size(valnode)); + if (slen < 0) { + return PLIST_ERR_UNKNOWN; + } + str_buf_append(*outbuf, buf, (size_t)slen); } else { str_buf_append(*outbuf, ": ", 2); } } cnt++; } - } break; + break; + } case PLIST_DATA: { + if (!node_data->buff && node_data->length > 0) { + return PLIST_ERR_INVALID_ARG; + } + if (node_data->length == 0) { + break; + } #define BASE64_CHUNK_SIZE 3072 #define BASE64_BUF_SIZE (4 * ((BASE64_CHUNK_SIZE + 2) / 3) + 4) val = (char*)malloc(BASE64_BUF_SIZE); @@ -216,6 +264,7 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de struct TM *btime = gmtime64_r(&timev, &_btime); if (btime) { val = (char*)calloc(1, 24); + if (!val) return PLIST_ERR_NO_MEM; struct tm _tmcopy; copy_TM64_to_tm(btime, &_tmcopy); val_len = strftime(val, 24, "%Y-%m-%dT%H:%M:%SZ", &_tmcopy); @@ -223,19 +272,27 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de str_buf_append(*outbuf, val, val_len); } free(val); - val = NULL; } } break; + case PLIST_UID: { str_buf_append(*outbuf, "CF$UID:", 7); val = (char*)malloc(64); + if (!val) { + return PLIST_ERR_NO_MEM; + } if (node_data->length == 16) { - val_len = snprintf(val, 64, "%" PRIu64, node_data->intval); + slen = snprintf(val, 64, "%" PRIu64, node_data->intval); } else { - val_len = snprintf(val, 64, "%" PRIi64, node_data->intval); + slen = snprintf(val, 64, "%" PRIi64, node_data->intval); + } + if (slen < 0) { + free(val); + return PLIST_ERR_UNKNOWN; } + val_len = (size_t)slen; str_buf_append(*outbuf, val, val_len); free(val); } -- cgit v1.1-32-gdbae