summaryrefslogtreecommitdiffstats
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
parent9d4f14a0ba93dc39d516b5e1c1cd107693b81629 (diff)
downloadlibplist-5546a8746558d088d90ba8f6cb52a50f886c9572.tar.gz
libplist-5546a8746558d088d90ba8f6cb52a50f886c9572.tar.bz2
out-limd: Properly handle snprintf and some smaller improvements
-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 @@
46 46
47static size_t dtostr(char *buf, size_t bufsize, double realval) 47static size_t dtostr(char *buf, size_t bufsize, double realval)
48{ 48{
49 size_t len = 0; 49 int slen = 0;
50 if (isnan(realval)) { 50 if (isnan(realval)) {
51 len = snprintf(buf, bufsize, "nan"); 51 slen = snprintf(buf, bufsize, "nan");
52 } else if (isinf(realval)) { 52 } else if (isinf(realval)) {
53 len = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-'); 53 slen = snprintf(buf, bufsize, "%cinfinity", (realval > 0.0) ? '+' : '-');
54 } else if (realval == 0.0f) { 54 } else if (realval == 0.0f) {
55 len = snprintf(buf, bufsize, "0.0"); 55 slen = snprintf(buf, bufsize, "0.0");
56 } else { 56 } else {
57 slen = snprintf(buf, bufsize, "%.*g", 17, realval);
58 if (slen < 0) {
59 return 0;
60 }
61 if (!buf || bufsize == 0) {
62 return (size_t)slen;
63 }
64 size_t len = (size_t)slen;
65 if (len >= bufsize) {
66 len = bufsize - 1;
67 }
57 size_t i = 0; 68 size_t i = 0;
58 len = snprintf(buf, bufsize, "%.*g", 17, realval); 69 for (i = 0; i < len; i++) {
59 for (i = 0; buf && i < len; i++) {
60 if (buf[i] == ',') { 70 if (buf[i] == ',') {
61 buf[i] = '.'; 71 buf[i] = '.';
62 break; 72 break;
@@ -64,8 +74,12 @@ static size_t dtostr(char *buf, size_t bufsize, double realval)
64 break; 74 break;
65 } 75 }
66 } 76 }
77 return len;
78 }
79 if (slen < 0) {
80 return 0;
67 } 81 }
68 return len; 82 return (size_t)slen;
69} 83}
70 84
71static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t depth, uint32_t indent) 85static 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
73 plist_data_t node_data = NULL; 87 plist_data_t node_data = NULL;
74 88
75 char *val = NULL; 89 char *val = NULL;
90 int slen = 0;
76 size_t val_len = 0; 91 size_t val_len = 0;
77 char buf[16]; 92 char buf[16];
78 93
79 uint32_t i = 0; 94 uint32_t i = 0;
80 95
81 if (!node) 96 if (!node || !outbuf || !*outbuf) {
82 return PLIST_ERR_INVALID_ARG; 97 return PLIST_ERR_INVALID_ARG;
98 }
83 99
84 node_data = plist_get_data(node); 100 node_data = plist_get_data(node);
101 if (!node_data) {
102 return PLIST_ERR_INVALID_ARG;
103 }
85 104
86 switch (node_data->type) 105 switch (node_data->type)
87 { 106 {
@@ -92,26 +111,37 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
92 } else { 111 } else {
93 str_buf_append(*outbuf, "false", 5); 112 str_buf_append(*outbuf, "false", 5);
94 } 113 }
114 break;
95 } 115 }
96 break;
97 116
98 case PLIST_NULL: 117 case PLIST_NULL:
99 str_buf_append(*outbuf, "null", 4); 118 str_buf_append(*outbuf, "null", 4);
100 break; 119 break;
101 120
102 case PLIST_INT: 121 case PLIST_INT:
103 val = (char*)malloc(64); 122 val = (char*)malloc(64);
123 if (!val) {
124 return PLIST_ERR_NO_MEM;
125 }
104 if (node_data->length == 16) { 126 if (node_data->length == 16) {
105 val_len = snprintf(val, 64, "%" PRIu64, node_data->intval); 127 slen = snprintf(val, 64, "%" PRIu64, node_data->intval);
106 } else { 128 } else {
107 val_len = snprintf(val, 64, "%" PRIi64, node_data->intval); 129 slen = snprintf(val, 64, "%" PRIi64, node_data->intval);
130 }
131 if (slen < 0) {
132 free(val);
133 return PLIST_ERR_UNKNOWN;
108 } 134 }
135 val_len = (size_t)slen;
109 str_buf_append(*outbuf, val, val_len); 136 str_buf_append(*outbuf, val, val_len);
110 free(val); 137 free(val);
111 break; 138 break;
112 139
113 case PLIST_REAL: 140 case PLIST_REAL:
114 val = (char*)malloc(64); 141 val = (char*)malloc(64);
142 if (!val) {
143 return PLIST_ERR_NO_MEM;
144 }
115 val_len = dtostr(val, 64, node_data->realval); 145 val_len = dtostr(val, 64, node_data->realval);
116 str_buf_append(*outbuf, val, val_len); 146 str_buf_append(*outbuf, val, val_len);
117 free(val); 147 free(val);
@@ -119,18 +149,21 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
119 149
120 case PLIST_STRING: 150 case PLIST_STRING:
121 case PLIST_KEY: { 151 case PLIST_KEY: {
152 if (!node_data->strval && node_data->length > 0) {
153 return PLIST_ERR_INVALID_ARG;
154 }
122 const char *charmap[32] = { 155 const char *charmap[32] = {
123 "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007", 156 "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007",
124 "\\b", "\\t", "\\n", "\\u000b", "\\f", "\\r", "\\u000e", "\\u000f", 157 "\\b", "\\t", "\\n", "\\u000b", "\\f", "\\r", "\\u000e", "\\u000f",
125 "\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017", 158 "\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017",
126 "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f", 159 "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f",
127 }; 160 };
161
128 size_t j = 0; 162 size_t j = 0;
129 size_t len = 0; 163 size_t len = node_data->length;
130 off_t start = 0; 164 size_t start = 0;
131 off_t cur = 0; 165 size_t cur = 0;
132 166
133 len = node_data->length;
134 for (j = 0; j < len; j++) { 167 for (j = 0; j < len; j++) {
135 unsigned char ch = (unsigned char)node_data->strval[j]; 168 unsigned char ch = (unsigned char)node_data->strval[j];
136 if (ch < 0x20) { 169 if (ch < 0x20) {
@@ -138,11 +171,12 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
138 str_buf_append(*outbuf, charmap[ch], (charmap[ch][1] == 'u') ? 6 : 2); 171 str_buf_append(*outbuf, charmap[ch], (charmap[ch][1] == 'u') ? 6 : 2);
139 start = cur+1; 172 start = cur+1;
140 } 173 }
174
141 cur++; 175 cur++;
142 } 176 }
143 str_buf_append(*outbuf, node_data->strval + start, cur - start); 177 str_buf_append(*outbuf, node_data->strval + start, cur - start);
144 } break; 178 break;
145 179 }
146 case PLIST_ARRAY: { 180 case PLIST_ARRAY: {
147 node_t ch; 181 node_t ch;
148 uint32_t cnt = 0; 182 uint32_t cnt = 0;
@@ -153,15 +187,19 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
153 str_buf_append(*outbuf, " ", 1); 187 str_buf_append(*outbuf, " ", 1);
154 } 188 }
155 } 189 }
156 size_t sl = sprintf(buf, "%u: ", cnt); 190 slen = snprintf(buf, sizeof(buf), "%u: ", cnt);
157 str_buf_append(*outbuf, buf, sl); 191 if (slen < 0) {
192 return PLIST_ERR_UNKNOWN;
193 }
194 str_buf_append(*outbuf, buf, (size_t)slen);
158 plist_err_t res = node_to_string(ch, outbuf, depth+1, indent); 195 plist_err_t res = node_to_string(ch, outbuf, depth+1, indent);
159 if (res < 0) { 196 if (res < 0) {
160 return res; 197 return res;
161 } 198 }
162 cnt++; 199 cnt++;
163 } 200 }
164 } break; 201 break;
202 }
165 case PLIST_DICT: { 203 case PLIST_DICT: {
166 node_t ch; 204 node_t ch;
167 uint32_t cnt = 0; 205 uint32_t cnt = 0;
@@ -179,17 +217,27 @@ static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t de
179 if (cnt % 2 == 0) { 217 if (cnt % 2 == 0) {
180 plist_t valnode = (plist_t)node_next_sibling(ch); 218 plist_t valnode = (plist_t)node_next_sibling(ch);
181 if (PLIST_IS_ARRAY(valnode)) { 219 if (PLIST_IS_ARRAY(valnode)) {
182 size_t sl = sprintf(buf, "[%u]:", plist_array_get_size(valnode)); 220 slen = snprintf(buf, sizeof(buf), "[%u]:", plist_array_get_size(valnode));
183 str_buf_append(*outbuf, buf, sl); 221 if (slen < 0) {
222 return PLIST_ERR_UNKNOWN;
223 }
224 str_buf_append(*outbuf, buf, (size_t)slen);
184 } else { 225 } else {
185 str_buf_append(*outbuf, ": ", 2); 226 str_buf_append(*outbuf, ": ", 2);
186 } 227 }
187 } 228 }
188 cnt++; 229 cnt++;
189 } 230 }
190 } break; 231 break;
232 }
191 case PLIST_DATA: 233 case PLIST_DATA:
192 { 234 {
235 if (!node_data->buff && node_data->length > 0) {
236 return PLIST_ERR_INVALID_ARG;
237 }
238 if (node_data->length == 0) {
239 break;
240 }
193#define BASE64_CHUNK_SIZE 3072 241#define BASE64_CHUNK_SIZE 3072
194#define BASE64_BUF_SIZE (4 * ((BASE64_CHUNK_SIZE + 2) / 3) + 4) 242#define BASE64_BUF_SIZE (4 * ((BASE64_CHUNK_SIZE + 2) / 3) + 4)
195 val = (char*)malloc(BASE64_BUF_SIZE); 243 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
216 struct TM *btime = gmtime64_r(&timev, &_btime); 264 struct TM *btime = gmtime64_r(&timev, &_btime);
217 if (btime) { 265 if (btime) {
218 val = (char*)calloc(1, 24); 266 val = (char*)calloc(1, 24);
267 if (!val) return PLIST_ERR_NO_MEM;
219 struct tm _tmcopy; 268 struct tm _tmcopy;
220 copy_TM64_to_tm(btime, &_tmcopy); 269 copy_TM64_to_tm(btime, &_tmcopy);
221 val_len = strftime(val, 24, "%Y-%m-%dT%H:%M:%SZ", &_tmcopy); 270 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
223 str_buf_append(*outbuf, val, val_len); 272 str_buf_append(*outbuf, val, val_len);
224 } 273 }
225 free(val); 274 free(val);
226 val = NULL;
227 } 275 }
228 } 276 }
229 break; 277 break;
278
230 case PLIST_UID: 279 case PLIST_UID:
231 { 280 {
232 str_buf_append(*outbuf, "CF$UID:", 7); 281 str_buf_append(*outbuf, "CF$UID:", 7);
233 val = (char*)malloc(64); 282 val = (char*)malloc(64);
283 if (!val) {
284 return PLIST_ERR_NO_MEM;
285 }
234 if (node_data->length == 16) { 286 if (node_data->length == 16) {
235 val_len = snprintf(val, 64, "%" PRIu64, node_data->intval); 287 slen = snprintf(val, 64, "%" PRIu64, node_data->intval);
236 } else { 288 } else {
237 val_len = snprintf(val, 64, "%" PRIi64, node_data->intval); 289 slen = snprintf(val, 64, "%" PRIi64, node_data->intval);
290 }
291 if (slen < 0) {
292 free(val);
293 return PLIST_ERR_UNKNOWN;
238 } 294 }
295 val_len = (size_t)slen;
239 str_buf_append(*outbuf, val, val_len); 296 str_buf_append(*outbuf, val, val_len);
240 free(val); 297 free(val);
241 } 298 }