summaryrefslogtreecommitdiffstats
path: root/src/out-limd.c
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2026-05-22 15:46:37 +0200
committerGravatar Nikias Bassen2026-05-22 15:46:37 +0200
commit5546a8746558d088d90ba8f6cb52a50f886c9572 (patch)
treeb66f9b4ab51736376f830770b4f16debb40970c1 /src/out-limd.c
parent9d4f14a0ba93dc39d516b5e1c1cd107693b81629 (diff)
downloadlibplist-5546a8746558d088d90ba8f6cb52a50f886c9572.tar.gz
libplist-5546a8746558d088d90ba8f6cb52a50f886c9572.tar.bz2
out-limd: Properly handle snprintf and some smaller improvements
Diffstat (limited to 'src/out-limd.c')
-rw-r--r--src/out-limd.c111
1 files 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);
}