summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/plist/plist.h24
-rw-r--r--src/bplist.c60
-rw-r--r--src/plist.c18
-rw-r--r--src/xplist.c61
4 files changed, 120 insertions, 43 deletions
diff --git a/include/plist/plist.h b/include/plist/plist.h
index 0f69d40..21fd8bd 100644
--- a/include/plist/plist.h
+++ b/include/plist/plist.h
@@ -117,6 +117,15 @@ extern "C"
PLIST_NONE /**< No type */
} plist_type;
+ typedef enum
+ {
+ PLIST_ERR_SUCCESS = 0, /**< operation successful */
+ PLIST_ERR_INVALID_ARG = -1, /**< one or more of the parameters are invalid */
+ PLIST_ERR_FORMAT = -2, /**< the plist contains nodes not compatible with the output format */
+ PLIST_ERR_PARSE = -3, /**< parsing of the input format failed */
+ PLIST_ERR_NO_MEM = -4, /**< not enough memory to handle the operation */
+ PLIST_ERR_UNKNOWN = -255 /**< an unspecified error occurred */
+ } plist_err_t;
/********************************************
* *
@@ -655,9 +664,10 @@ extern "C"
* @param plist_xml a pointer to a C-string. This function allocates the memory,
* caller is responsible for freeing it. Data is UTF-8 encoded.
* @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer.
+ * @return PLIST_ERR_SUCCESS on success or a #plist_error on failure
* @note Use plist_mem_free() to free the allocated memory.
*/
- void plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length);
+ plist_err_t plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length);
/**
* Export the #plist_t structure to binary format.
@@ -666,9 +676,10 @@ extern "C"
* @param plist_bin a pointer to a char* buffer. This function allocates the memory,
* caller is responsible for freeing it.
* @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer.
+ * @return PLIST_ERR_SUCCESS on success or a #plist_error on failure
* @note Use plist_mem_free() to free the allocated memory.
*/
- void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length);
+ plist_err_t plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length);
/**
* Import the #plist_t structure from XML format.
@@ -676,8 +687,9 @@ extern "C"
* @param plist_xml a pointer to the xml buffer.
* @param length length of the buffer to read.
* @param plist a pointer to the imported plist.
+ * @return PLIST_ERR_SUCCESS on success or a #plist_error on failure
*/
- void plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist);
+ plist_err_t plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist);
/**
* Import the #plist_t structure from binary format.
@@ -685,8 +697,9 @@ extern "C"
* @param plist_bin a pointer to the xml buffer.
* @param length length of the buffer to read.
* @param plist a pointer to the imported plist.
+ * @return PLIST_ERR_SUCCESS on success or a #plist_error on failure
*/
- void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist);
+ plist_err_t plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist);
/**
* Import the #plist_t structure from memory data.
@@ -696,8 +709,9 @@ extern "C"
* @param plist_data a pointer to the memory buffer containing plist data.
* @param length length of the buffer to read.
* @param plist a pointer to the imported plist.
+ * @return PLIST_ERR_SUCCESS on success or a #plist_error on failure
*/
- void plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist);
+ plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist);
/**
* Test if in-memory plist data is binary or XML
diff --git a/src/bplist.c b/src/bplist.c
index a6e6ded..57ec151 100644
--- a/src/bplist.c
+++ b/src/bplist.c
@@ -774,7 +774,7 @@ static plist_t parse_bin_node_at_index(struct bplist_data *bplist, uint32_t node
return plist;
}
-PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist)
+PLIST_API plist_err_t plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist)
{
bplist_trailer_t *trailer = NULL;
uint8_t offset_size = 0;
@@ -786,20 +786,28 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
const char *start_data = NULL;
const char *end_data = NULL;
+ if (!plist) {
+ return PLIST_ERR_INVALID_ARG;
+ }
+ *plist = NULL;
+ if (!plist_bin || length == 0) {
+ return PLIST_ERR_INVALID_ARG;
+ }
+
//first check we have enough data
if (!(length >= BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE + sizeof(bplist_trailer_t))) {
PLIST_BIN_ERR("plist data is to small to hold a binary plist\n");
- return;
+ return PLIST_ERR_PARSE;
}
//check that plist_bin in actually a plist
if (memcmp(plist_bin, BPLIST_MAGIC, BPLIST_MAGIC_SIZE) != 0) {
PLIST_BIN_ERR("bplist magic mismatch\n");
- return;
+ return PLIST_ERR_PARSE;
}
//check for known version
if (memcmp(plist_bin + BPLIST_MAGIC_SIZE, BPLIST_VERSION, BPLIST_VERSION_SIZE) != 0) {
PLIST_BIN_ERR("unsupported binary plist version '%.2s\n", plist_bin+BPLIST_MAGIC_SIZE);
- return;
+ return PLIST_ERR_PARSE;
}
start_data = plist_bin + BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE;
@@ -816,37 +824,37 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
if (num_objects == 0) {
PLIST_BIN_ERR("number of objects must be larger than 0\n");
- return;
+ return PLIST_ERR_PARSE;
}
if (offset_size == 0) {
PLIST_BIN_ERR("offset size in trailer must be larger than 0\n");
- return;
+ return PLIST_ERR_PARSE;
}
if (ref_size == 0) {
PLIST_BIN_ERR("object reference size in trailer must be larger than 0\n");
- return;
+ return PLIST_ERR_PARSE;
}
if (root_object >= num_objects) {
PLIST_BIN_ERR("root object index (%" PRIu64 ") must be smaller than number of objects (%" PRIu64 ")\n", root_object, num_objects);
- return;
+ return PLIST_ERR_PARSE;
}
if (offset_table < start_data || offset_table >= end_data) {
PLIST_BIN_ERR("offset table offset points outside of valid range\n");
- return;
+ return PLIST_ERR_PARSE;
}
if (uint64_mul_overflow(num_objects, offset_size, &offset_table_size)) {
PLIST_BIN_ERR("integer overflow when calculating offset table size\n");
- return;
+ return PLIST_ERR_PARSE;
}
if (offset_table_size > (uint64_t)(end_data - offset_table)) {
PLIST_BIN_ERR("offset table points outside of valid range\n");
- return;
+ return PLIST_ERR_PARSE;
}
struct bplist_data bplist;
@@ -861,12 +869,18 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
if (!bplist.used_indexes) {
PLIST_BIN_ERR("failed to create array to hold used node indexes. Out of memory?\n");
- return;
+ return PLIST_ERR_NO_MEM;
}
*plist = parse_bin_node_at_index(&bplist, root_object);
ptr_array_free(bplist.used_indexes);
+
+ if (!*plist) {
+ return PLIST_ERR_PARSE;
+ }
+
+ return PLIST_ERR_SUCCESS;
}
static unsigned int plist_data_hash(const void* key)
@@ -1163,7 +1177,7 @@ static int is_ascii_string(char* s, int len)
return ret;
}
-PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
+PLIST_API plist_err_t plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
{
ptrarray_t* objects = NULL;
hashtable_t* ref_table = NULL;
@@ -1181,13 +1195,21 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
uint64_t objects_len = 0;
//check for valid input
- if (!plist || !plist_bin || *plist_bin || !length)
- return;
+ if (!plist || !plist_bin || !length) {
+ return PLIST_ERR_INVALID_ARG;
+ }
//list of objects
objects = ptr_array_new(4096);
+ if (!objects) {
+ return PLIST_ERR_NO_MEM;
+ }
//hashtable to write only once same nodes
ref_table = hash_table_new(plist_data_hash, plist_data_compare, free);
+ if (!ref_table) {
+ ptr_array_free(objects);
+ return PLIST_ERR_NO_MEM;
+ }
//serialize plist
ser_s.objects = objects;
@@ -1212,6 +1234,7 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
uint8_t bsize;
switch (data->type)
{
+ case PLIST_NULL:
case PLIST_BOOLEAN:
req += 1;
break;
@@ -1286,6 +1309,11 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
//setup a dynamic bytes array to store bplist in
bplist_buff = byte_array_new(req);
+ if (!bplist_buff) {
+ ptr_array_free(objects);
+ hash_table_destroy(ref_table);
+ return PLIST_ERR_NO_MEM;
+ }
//set magic number and version
byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE);
@@ -1385,4 +1413,6 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
bplist_buff->data = NULL; // make sure we don't free the output buffer
byte_array_free(bplist_buff);
+
+ return PLIST_ERR_SUCCESS;
}
diff --git a/src/plist.c b/src/plist.c
index 5453176..61b2913 100644
--- a/src/plist.c
+++ b/src/plist.c
@@ -183,18 +183,22 @@ PLIST_API int plist_is_binary(const char *plist_data, uint32_t length)
}
-PLIST_API void plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist)
+PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist)
{
- if (length < 8) {
- *plist = NULL;
- return;
+ int res = -1;
+ if (!plist) {
+ return PLIST_ERR_INVALID_ARG;
+ }
+ *plist = NULL;
+ if (!plist_data || length < 8) {
+ return PLIST_ERR_INVALID_ARG;
}
-
if (plist_is_binary(plist_data, length)) {
- plist_from_bin(plist_data, length, plist);
+ res = plist_from_bin(plist_data, length, plist);
} else {
- plist_from_xml(plist_data, length, plist);
+ res = plist_from_xml(plist_data, length, plist);
}
+ return res;
}
plist_t plist_new_node(plist_data_t data)
diff --git a/src/xplist.c b/src/xplist.c
index 94006f1..3971622 100644
--- a/src/xplist.c
+++ b/src/xplist.c
@@ -143,7 +143,7 @@ static int node_to_xml(node_t* node, bytearray_t **outbuf, uint32_t depth)
if (!node) {
PLIST_XML_WRITE_ERR("Encountered invalid empty node in property list\n");
- return -1;
+ return PLIST_ERR_INVALID_ARG;
}
node_data = plist_get_data(node);
@@ -238,9 +238,9 @@ static int node_to_xml(node_t* node, bytearray_t **outbuf, uint32_t depth)
break;
case PLIST_NULL:
PLIST_XML_WRITE_ERR("PLIST_NULL type is not valid for XML format\n");
- return -1;
+ return PLIST_ERR_FORMAT;
default:
- break;
+ return PLIST_ERR_UNKNOWN;
}
for (i = 0; i < depth; i++) {
@@ -377,7 +377,7 @@ static int node_to_xml(node_t* node, bytearray_t **outbuf, uint32_t depth)
str_buf_append(*outbuf, ">", 1);
}
str_buf_append(*outbuf, "\n", 1);
- return 0;
+ return PLIST_ERR_SUCCESS;
}
static void parse_date(const char *strval, struct TM *btime)
@@ -438,11 +438,11 @@ static int num_digits_u(uint64_t i)
return n;
}
-static void node_estimate_size(node_t *node, uint64_t *size, uint32_t depth)
+static int node_estimate_size(node_t *node, uint64_t *size, uint32_t depth)
{
plist_data_t data;
if (!node) {
- return;
+ return PLIST_ERR_INVALID_ARG;
}
data = plist_get_data(node);
if (node->children) {
@@ -511,28 +511,47 @@ static void node_estimate_size(node_t *node, uint64_t *size, uint32_t depth)
*size += 18; /* <key>CF$UID</key> */
*size += (XPLIST_INT_LEN << 1) + 6;
break;
+ case PLIST_NULL:
+ PLIST_XML_WRITE_ERR("PLIST_NULL type is not valid for XML format\n");
+ return PLIST_ERR_FORMAT;
default:
- break;
+ PLIST_XML_WRITE_ERR("invalid node type encountered\n");
+ return PLIST_ERR_UNKNOWN;
}
*size += indent;
}
+ return PLIST_ERR_SUCCESS;
}
-PLIST_API void plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length)
+PLIST_API plist_err_t plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length)
{
uint64_t size = 0;
- node_estimate_size(plist, &size, 0);
+ int res;
+
+ if (!plist || !plist_xml || !length) {
+ return PLIST_ERR_INVALID_ARG;
+ }
+
+ res = node_estimate_size(plist, &size, 0);
+ if (res < 0) {
+ return res;
+ }
size += sizeof(XML_PLIST_PROLOG) + sizeof(XML_PLIST_EPILOG) - 1;
strbuf_t *outbuf = str_buf_new(size);
+ if (!outbuf) {
+ PLIST_XML_WRITE_ERR("Could not allocate output buffer");
+ return PLIST_ERR_NO_MEM;
+ }
str_buf_append(outbuf, XML_PLIST_PROLOG, sizeof(XML_PLIST_PROLOG)-1);
- if (node_to_xml(plist, &outbuf, 0) < 0) {
+ res = node_to_xml(plist, &outbuf, 0);
+ if (res < 0) {
str_buf_free(outbuf);
*plist_xml = NULL;
*length = 0;
- return;
+ return res;
}
str_buf_append(outbuf, XML_PLIST_EPILOG, sizeof(XML_PLIST_EPILOG));
@@ -542,6 +561,8 @@ PLIST_API void plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length)
outbuf->data = NULL;
str_buf_free(outbuf);
+
+ return PLIST_ERR_SUCCESS;
}
struct _parse_ctx {
@@ -932,8 +953,9 @@ static char* text_parts_get_content(text_part_t *tp, int unesc_entities, size_t
return str;
}
-static void node_from_xml(parse_ctx ctx, plist_t *plist)
+static int node_from_xml(parse_ctx ctx, plist_t *plist)
{
+ int res;
char *tag = NULL;
char *keyname = NULL;
plist_t subnode = NULL;
@@ -1427,17 +1449,24 @@ err_out:
if (ctx->err) {
plist_free(*plist);
*plist = NULL;
+ res = PLIST_ERR_PARSE;
+ } else {
+ res = PLIST_ERR_SUCCESS;
}
+ return res;
}
-PLIST_API void plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist)
+PLIST_API plist_err_t plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist)
{
+ if (!plist) {
+ return PLIST_ERR_INVALID_ARG;
+ }
+ *plist = NULL;
if (!plist_xml || (length == 0)) {
- *plist = NULL;
- return;
+ return PLIST_ERR_INVALID_ARG;
}
struct _parse_ctx ctx = { plist_xml, plist_xml + length, 0 };
- node_from_xml(&ctx, plist);
+ return node_from_xml(&ctx, plist);
}