diff options
author | Nikias Bassen <nikias@gmx.li> | 2014-05-23 11:01:57 +0200 |
---|---|---|
committer | Nikias Bassen <nikias@gmx.li> | 2014-05-23 11:01:57 +0200 |
commit | 6c0bf73f0773873edf8754246c291235aa217e7a (patch) | |
tree | c8b3023f702ff98cb92cb437ed65b37a7e6b1797 | |
parent | 8ac53f53b60e0ac22b4f41f67c3f1f0526e1abb2 (diff) | |
download | libplist-6c0bf73f0773873edf8754246c291235aa217e7a.tar.gz |
Handle signed vs. unsigned integer values correctly
-rw-r--r-- | src/bplist.c | 27 | ||||
-rw-r--r-- | src/xplist.c | 31 |
2 files changed, 53 insertions, 5 deletions
diff --git a/src/bplist.c b/src/bplist.c index d1694b9..c4b2e13 100644 --- a/src/bplist.c +++ b/src/bplist.c @@ -212,6 +212,12 @@ static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) case sizeof(uint64_t): memcpy(&data->intval, bnode, size); data->intval = UINT_TO_HOST(&data->intval, size); + data->length = sizeof(uint64_t); + break; + case 16: + memcpy(&data->intval, bnode+8, sizeof(uint64_t)); + data->intval = UINT_TO_HOST(&data->intval, sizeof(uint64_t)); + data->length = size; break; default: free(data); @@ -220,7 +226,6 @@ static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) *next_object = bnode + size; data->type = PLIST_UINT; - data->length = sizeof(uint64_t); return node_create(NULL, data); } @@ -833,6 +838,20 @@ static void write_int(bytearray_t * bplist, uint64_t val) free(buff); } +static void write_uint(bytearray_t * bplist, uint64_t val) +{ + uint64_t size = 16; + uint8_t *buff = NULL; + + buff = (uint8_t *) malloc(sizeof(uint8_t) + size); + buff[0] = BPLIST_UINT | 4; + memset(buff + 1, '\0', 8); + memcpy(buff + 9, &val, 8); + byte_convert(buff + 9, 8); + byte_array_append(bplist, buff, sizeof(uint8_t) + size); + free(buff); +} + static void write_real(bytearray_t * bplist, double val) { uint64_t size = get_real_bytes(val); //cheat to know used space @@ -1143,7 +1162,11 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) break; case PLIST_UINT: - write_int(bplist_buff, data->intval); + if (data->length == 16) { + write_uint(bplist_buff, data->intval); + } else { + write_int(bplist_buff, data->intval); + } break; case PLIST_REAL: diff --git a/src/xplist.c b/src/xplist.c index d953e23..eaa2468 100644 --- a/src/xplist.c +++ b/src/xplist.c @@ -184,7 +184,11 @@ static void node_to_xml(node_t* node, void *xml_struct) case PLIST_UINT: tag = XPLIST_INT; val = (char*)malloc(64); - (void)snprintf(val, 64, "%"PRIu64, node_data->intval); + if (node_data->length == 16) { + (void)snprintf(val, 64, "%"PRIu64, node_data->intval); + } else { + (void)snprintf(val, 64, "%"PRIi64, node_data->intval); + } break; case PLIST_REAL: @@ -377,9 +381,30 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) if (!xmlStrcmp(node->name, XPLIST_INT)) { xmlChar *strval = xmlNodeGetContent(node); - data->intval = strtoull((char*)strval, NULL, 0); + int is_negative = 0; + char *str = (char*)strval; + if ((str[0] == '-') || (str[0] == '+')) { + if (str[0] == '-') { + is_negative = 1; + } + str++; + } + char* endp = NULL; + data->intval = strtoull((char*)str, &endp, 0); + if ((endp != NULL) && (strlen(endp) > 0)) { + fprintf(stderr, "%s: integer parse error: string contains invalid characters: '%s'\n", __func__, endp); + } + if (is_negative || (data->intval <= INT64_MAX)) { + int64_t v = data->intval; + if (is_negative) { + v = -v; + } + data->intval = (uint64_t)v; + data->length = 8; + } else { + data->length = 16; + } data->type = PLIST_UINT; - data->length = 8; xmlFree(strval); continue; } |