diff options
| -rw-r--r-- | src/out-limd.c | 111 |
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 | ||
| 47 | static size_t dtostr(char *buf, size_t bufsize, double realval) | 47 | static 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 | ||
| 71 | static plist_err_t node_to_string(node_t node, bytearray_t **outbuf, uint32_t depth, uint32_t indent) | 85 | 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 | |||
| 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 | } |
