summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2021-12-22 03:17:26 +0100
committerGravatar Nikias Bassen2021-12-22 03:17:26 +0100
commit70f4a422e01910cdb783aac81f13c11223c3acbd (patch)
tree1279c0edd8b84b91d6a9bc757ea5dc8232f4d78f
parent810e1a5936867a9f2c9f07df3a33a9d02fc03466 (diff)
downloadlibplist-70f4a422e01910cdb783aac81f13c11223c3acbd.tar.gz
libplist-70f4a422e01910cdb783aac81f13c11223c3acbd.tar.bz2
Add a return value to plist_to_* and plist_from_* functions
This way it can be easier determined why an import/export operation failed instead of just having a NULL result.
-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"
117 PLIST_NONE /**< No type */ 117 PLIST_NONE /**< No type */
118 } plist_type; 118 } plist_type;
119 119
120 typedef enum
121 {
122 PLIST_ERR_SUCCESS = 0, /**< operation successful */
123 PLIST_ERR_INVALID_ARG = -1, /**< one or more of the parameters are invalid */
124 PLIST_ERR_FORMAT = -2, /**< the plist contains nodes not compatible with the output format */
125 PLIST_ERR_PARSE = -3, /**< parsing of the input format failed */
126 PLIST_ERR_NO_MEM = -4, /**< not enough memory to handle the operation */
127 PLIST_ERR_UNKNOWN = -255 /**< an unspecified error occurred */
128 } plist_err_t;
120 129
121 /******************************************** 130 /********************************************
122 * * 131 * *
@@ -655,9 +664,10 @@ extern "C"
655 * @param plist_xml a pointer to a C-string. This function allocates the memory, 664 * @param plist_xml a pointer to a C-string. This function allocates the memory,
656 * caller is responsible for freeing it. Data is UTF-8 encoded. 665 * caller is responsible for freeing it. Data is UTF-8 encoded.
657 * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer. 666 * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer.
667 * @return PLIST_ERR_SUCCESS on success or a #plist_error on failure
658 * @note Use plist_mem_free() to free the allocated memory. 668 * @note Use plist_mem_free() to free the allocated memory.
659 */ 669 */
660 void plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length); 670 plist_err_t plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length);
661 671
662 /** 672 /**
663 * Export the #plist_t structure to binary format. 673 * Export the #plist_t structure to binary format.
@@ -666,9 +676,10 @@ extern "C"
666 * @param plist_bin a pointer to a char* buffer. This function allocates the memory, 676 * @param plist_bin a pointer to a char* buffer. This function allocates the memory,
667 * caller is responsible for freeing it. 677 * caller is responsible for freeing it.
668 * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer. 678 * @param length a pointer to an uint32_t variable. Represents the length of the allocated buffer.
679 * @return PLIST_ERR_SUCCESS on success or a #plist_error on failure
669 * @note Use plist_mem_free() to free the allocated memory. 680 * @note Use plist_mem_free() to free the allocated memory.
670 */ 681 */
671 void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length); 682 plist_err_t plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length);
672 683
673 /** 684 /**
674 * Import the #plist_t structure from XML format. 685 * Import the #plist_t structure from XML format.
@@ -676,8 +687,9 @@ extern "C"
676 * @param plist_xml a pointer to the xml buffer. 687 * @param plist_xml a pointer to the xml buffer.
677 * @param length length of the buffer to read. 688 * @param length length of the buffer to read.
678 * @param plist a pointer to the imported plist. 689 * @param plist a pointer to the imported plist.
690 * @return PLIST_ERR_SUCCESS on success or a #plist_error on failure
679 */ 691 */
680 void plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist); 692 plist_err_t plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist);
681 693
682 /** 694 /**
683 * Import the #plist_t structure from binary format. 695 * Import the #plist_t structure from binary format.
@@ -685,8 +697,9 @@ extern "C"
685 * @param plist_bin a pointer to the xml buffer. 697 * @param plist_bin a pointer to the xml buffer.
686 * @param length length of the buffer to read. 698 * @param length length of the buffer to read.
687 * @param plist a pointer to the imported plist. 699 * @param plist a pointer to the imported plist.
700 * @return PLIST_ERR_SUCCESS on success or a #plist_error on failure
688 */ 701 */
689 void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist); 702 plist_err_t plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist);
690 703
691 /** 704 /**
692 * Import the #plist_t structure from memory data. 705 * Import the #plist_t structure from memory data.
@@ -696,8 +709,9 @@ extern "C"
696 * @param plist_data a pointer to the memory buffer containing plist data. 709 * @param plist_data a pointer to the memory buffer containing plist data.
697 * @param length length of the buffer to read. 710 * @param length length of the buffer to read.
698 * @param plist a pointer to the imported plist. 711 * @param plist a pointer to the imported plist.
712 * @return PLIST_ERR_SUCCESS on success or a #plist_error on failure
699 */ 713 */
700 void plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist); 714 plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist);
701 715
702 /** 716 /**
703 * Test if in-memory plist data is binary or XML 717 * 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
774 return plist; 774 return plist;
775} 775}
776 776
777PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) 777PLIST_API plist_err_t plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist)
778{ 778{
779 bplist_trailer_t *trailer = NULL; 779 bplist_trailer_t *trailer = NULL;
780 uint8_t offset_size = 0; 780 uint8_t offset_size = 0;
@@ -786,20 +786,28 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
786 const char *start_data = NULL; 786 const char *start_data = NULL;
787 const char *end_data = NULL; 787 const char *end_data = NULL;
788 788
789 if (!plist) {
790 return PLIST_ERR_INVALID_ARG;
791 }
792 *plist = NULL;
793 if (!plist_bin || length == 0) {
794 return PLIST_ERR_INVALID_ARG;
795 }
796
789 //first check we have enough data 797 //first check we have enough data
790 if (!(length >= BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE + sizeof(bplist_trailer_t))) { 798 if (!(length >= BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE + sizeof(bplist_trailer_t))) {
791 PLIST_BIN_ERR("plist data is to small to hold a binary plist\n"); 799 PLIST_BIN_ERR("plist data is to small to hold a binary plist\n");
792 return; 800 return PLIST_ERR_PARSE;
793 } 801 }
794 //check that plist_bin in actually a plist 802 //check that plist_bin in actually a plist
795 if (memcmp(plist_bin, BPLIST_MAGIC, BPLIST_MAGIC_SIZE) != 0) { 803 if (memcmp(plist_bin, BPLIST_MAGIC, BPLIST_MAGIC_SIZE) != 0) {
796 PLIST_BIN_ERR("bplist magic mismatch\n"); 804 PLIST_BIN_ERR("bplist magic mismatch\n");
797 return; 805 return PLIST_ERR_PARSE;
798 } 806 }
799 //check for known version 807 //check for known version
800 if (memcmp(plist_bin + BPLIST_MAGIC_SIZE, BPLIST_VERSION, BPLIST_VERSION_SIZE) != 0) { 808 if (memcmp(plist_bin + BPLIST_MAGIC_SIZE, BPLIST_VERSION, BPLIST_VERSION_SIZE) != 0) {
801 PLIST_BIN_ERR("unsupported binary plist version '%.2s\n", plist_bin+BPLIST_MAGIC_SIZE); 809 PLIST_BIN_ERR("unsupported binary plist version '%.2s\n", plist_bin+BPLIST_MAGIC_SIZE);
802 return; 810 return PLIST_ERR_PARSE;
803 } 811 }
804 812
805 start_data = plist_bin + BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE; 813 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 *
816 824
817 if (num_objects == 0) { 825 if (num_objects == 0) {
818 PLIST_BIN_ERR("number of objects must be larger than 0\n"); 826 PLIST_BIN_ERR("number of objects must be larger than 0\n");
819 return; 827 return PLIST_ERR_PARSE;
820 } 828 }
821 829
822 if (offset_size == 0) { 830 if (offset_size == 0) {
823 PLIST_BIN_ERR("offset size in trailer must be larger than 0\n"); 831 PLIST_BIN_ERR("offset size in trailer must be larger than 0\n");
824 return; 832 return PLIST_ERR_PARSE;
825 } 833 }
826 834
827 if (ref_size == 0) { 835 if (ref_size == 0) {
828 PLIST_BIN_ERR("object reference size in trailer must be larger than 0\n"); 836 PLIST_BIN_ERR("object reference size in trailer must be larger than 0\n");
829 return; 837 return PLIST_ERR_PARSE;
830 } 838 }
831 839
832 if (root_object >= num_objects) { 840 if (root_object >= num_objects) {
833 PLIST_BIN_ERR("root object index (%" PRIu64 ") must be smaller than number of objects (%" PRIu64 ")\n", root_object, num_objects); 841 PLIST_BIN_ERR("root object index (%" PRIu64 ") must be smaller than number of objects (%" PRIu64 ")\n", root_object, num_objects);
834 return; 842 return PLIST_ERR_PARSE;
835 } 843 }
836 844
837 if (offset_table < start_data || offset_table >= end_data) { 845 if (offset_table < start_data || offset_table >= end_data) {
838 PLIST_BIN_ERR("offset table offset points outside of valid range\n"); 846 PLIST_BIN_ERR("offset table offset points outside of valid range\n");
839 return; 847 return PLIST_ERR_PARSE;
840 } 848 }
841 849
842 if (uint64_mul_overflow(num_objects, offset_size, &offset_table_size)) { 850 if (uint64_mul_overflow(num_objects, offset_size, &offset_table_size)) {
843 PLIST_BIN_ERR("integer overflow when calculating offset table size\n"); 851 PLIST_BIN_ERR("integer overflow when calculating offset table size\n");
844 return; 852 return PLIST_ERR_PARSE;
845 } 853 }
846 854
847 if (offset_table_size > (uint64_t)(end_data - offset_table)) { 855 if (offset_table_size > (uint64_t)(end_data - offset_table)) {
848 PLIST_BIN_ERR("offset table points outside of valid range\n"); 856 PLIST_BIN_ERR("offset table points outside of valid range\n");
849 return; 857 return PLIST_ERR_PARSE;
850 } 858 }
851 859
852 struct bplist_data bplist; 860 struct bplist_data bplist;
@@ -861,12 +869,18 @@ PLIST_API void plist_from_bin(const char *plist_bin, uint32_t length, plist_t *
861 869
862 if (!bplist.used_indexes) { 870 if (!bplist.used_indexes) {
863 PLIST_BIN_ERR("failed to create array to hold used node indexes. Out of memory?\n"); 871 PLIST_BIN_ERR("failed to create array to hold used node indexes. Out of memory?\n");
864 return; 872 return PLIST_ERR_NO_MEM;
865 } 873 }
866 874
867 *plist = parse_bin_node_at_index(&bplist, root_object); 875 *plist = parse_bin_node_at_index(&bplist, root_object);
868 876
869 ptr_array_free(bplist.used_indexes); 877 ptr_array_free(bplist.used_indexes);
878
879 if (!*plist) {
880 return PLIST_ERR_PARSE;
881 }
882
883 return PLIST_ERR_SUCCESS;
870} 884}
871 885
872static unsigned int plist_data_hash(const void* key) 886static unsigned int plist_data_hash(const void* key)
@@ -1163,7 +1177,7 @@ static int is_ascii_string(char* s, int len)
1163 return ret; 1177 return ret;
1164} 1178}
1165 1179
1166PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) 1180PLIST_API plist_err_t plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
1167{ 1181{
1168 ptrarray_t* objects = NULL; 1182 ptrarray_t* objects = NULL;
1169 hashtable_t* ref_table = NULL; 1183 hashtable_t* ref_table = NULL;
@@ -1181,13 +1195,21 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
1181 uint64_t objects_len = 0; 1195 uint64_t objects_len = 0;
1182 1196
1183 //check for valid input 1197 //check for valid input
1184 if (!plist || !plist_bin || *plist_bin || !length) 1198 if (!plist || !plist_bin || !length) {
1185 return; 1199 return PLIST_ERR_INVALID_ARG;
1200 }
1186 1201
1187 //list of objects 1202 //list of objects
1188 objects = ptr_array_new(4096); 1203 objects = ptr_array_new(4096);
1204 if (!objects) {
1205 return PLIST_ERR_NO_MEM;
1206 }
1189 //hashtable to write only once same nodes 1207 //hashtable to write only once same nodes
1190 ref_table = hash_table_new(plist_data_hash, plist_data_compare, free); 1208 ref_table = hash_table_new(plist_data_hash, plist_data_compare, free);
1209 if (!ref_table) {
1210 ptr_array_free(objects);
1211 return PLIST_ERR_NO_MEM;
1212 }
1191 1213
1192 //serialize plist 1214 //serialize plist
1193 ser_s.objects = objects; 1215 ser_s.objects = objects;
@@ -1212,6 +1234,7 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
1212 uint8_t bsize; 1234 uint8_t bsize;
1213 switch (data->type) 1235 switch (data->type)
1214 { 1236 {
1237 case PLIST_NULL:
1215 case PLIST_BOOLEAN: 1238 case PLIST_BOOLEAN:
1216 req += 1; 1239 req += 1;
1217 break; 1240 break;
@@ -1286,6 +1309,11 @@ PLIST_API void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
1286 1309
1287 //setup a dynamic bytes array to store bplist in 1310 //setup a dynamic bytes array to store bplist in
1288 bplist_buff = byte_array_new(req); 1311 bplist_buff = byte_array_new(req);
1312 if (!bplist_buff) {
1313 ptr_array_free(objects);
1314 hash_table_destroy(ref_table);
1315 return PLIST_ERR_NO_MEM;
1316 }
1289 1317
1290 //set magic number and version 1318 //set magic number and version
1291 byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); 1319 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)
1385 1413
1386 bplist_buff->data = NULL; // make sure we don't free the output buffer 1414 bplist_buff->data = NULL; // make sure we don't free the output buffer
1387 byte_array_free(bplist_buff); 1415 byte_array_free(bplist_buff);
1416
1417 return PLIST_ERR_SUCCESS;
1388} 1418}
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)
183} 183}
184 184
185 185
186PLIST_API void plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist) 186PLIST_API plist_err_t plist_from_memory(const char *plist_data, uint32_t length, plist_t * plist)
187{ 187{
188 if (length < 8) { 188 int res = -1;
189 *plist = NULL; 189 if (!plist) {
190 return; 190 return PLIST_ERR_INVALID_ARG;
191 }
192 *plist = NULL;
193 if (!plist_data || length < 8) {
194 return PLIST_ERR_INVALID_ARG;
191 } 195 }
192
193 if (plist_is_binary(plist_data, length)) { 196 if (plist_is_binary(plist_data, length)) {
194 plist_from_bin(plist_data, length, plist); 197 res = plist_from_bin(plist_data, length, plist);
195 } else { 198 } else {
196 plist_from_xml(plist_data, length, plist); 199 res = plist_from_xml(plist_data, length, plist);
197 } 200 }
201 return res;
198} 202}
199 203
200plist_t plist_new_node(plist_data_t data) 204plist_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)
143 143
144 if (!node) { 144 if (!node) {
145 PLIST_XML_WRITE_ERR("Encountered invalid empty node in property list\n"); 145 PLIST_XML_WRITE_ERR("Encountered invalid empty node in property list\n");
146 return -1; 146 return PLIST_ERR_INVALID_ARG;
147 } 147 }
148 148
149 node_data = plist_get_data(node); 149 node_data = plist_get_data(node);
@@ -238,9 +238,9 @@ static int node_to_xml(node_t* node, bytearray_t **outbuf, uint32_t depth)
238 break; 238 break;
239 case PLIST_NULL: 239 case PLIST_NULL:
240 PLIST_XML_WRITE_ERR("PLIST_NULL type is not valid for XML format\n"); 240 PLIST_XML_WRITE_ERR("PLIST_NULL type is not valid for XML format\n");
241 return -1; 241 return PLIST_ERR_FORMAT;
242 default: 242 default:
243 break; 243 return PLIST_ERR_UNKNOWN;
244 } 244 }
245 245
246 for (i = 0; i < depth; i++) { 246 for (i = 0; i < depth; i++) {
@@ -377,7 +377,7 @@ static int node_to_xml(node_t* node, bytearray_t **outbuf, uint32_t depth)
377 str_buf_append(*outbuf, ">", 1); 377 str_buf_append(*outbuf, ">", 1);
378 } 378 }
379 str_buf_append(*outbuf, "\n", 1); 379 str_buf_append(*outbuf, "\n", 1);
380 return 0; 380 return PLIST_ERR_SUCCESS;
381} 381}
382 382
383static void parse_date(const char *strval, struct TM *btime) 383static void parse_date(const char *strval, struct TM *btime)
@@ -438,11 +438,11 @@ static int num_digits_u(uint64_t i)
438 return n; 438 return n;
439} 439}
440 440
441static void node_estimate_size(node_t *node, uint64_t *size, uint32_t depth) 441static int node_estimate_size(node_t *node, uint64_t *size, uint32_t depth)
442{ 442{
443 plist_data_t data; 443 plist_data_t data;
444 if (!node) { 444 if (!node) {
445 return; 445 return PLIST_ERR_INVALID_ARG;
446 } 446 }
447 data = plist_get_data(node); 447 data = plist_get_data(node);
448 if (node->children) { 448 if (node->children) {
@@ -511,28 +511,47 @@ static void node_estimate_size(node_t *node, uint64_t *size, uint32_t depth)
511 *size += 18; /* <key>CF$UID</key> */ 511 *size += 18; /* <key>CF$UID</key> */
512 *size += (XPLIST_INT_LEN << 1) + 6; 512 *size += (XPLIST_INT_LEN << 1) + 6;
513 break; 513 break;
514 case PLIST_NULL:
515 PLIST_XML_WRITE_ERR("PLIST_NULL type is not valid for XML format\n");
516 return PLIST_ERR_FORMAT;
514 default: 517 default:
515 break; 518 PLIST_XML_WRITE_ERR("invalid node type encountered\n");
519 return PLIST_ERR_UNKNOWN;
516 } 520 }
517 *size += indent; 521 *size += indent;
518 } 522 }
523 return PLIST_ERR_SUCCESS;
519} 524}
520 525
521PLIST_API void plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length) 526PLIST_API plist_err_t plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length)
522{ 527{
523 uint64_t size = 0; 528 uint64_t size = 0;
524 node_estimate_size(plist, &size, 0); 529 int res;
530
531 if (!plist || !plist_xml || !length) {
532 return PLIST_ERR_INVALID_ARG;
533 }
534
535 res = node_estimate_size(plist, &size, 0);
536 if (res < 0) {
537 return res;
538 }
525 size += sizeof(XML_PLIST_PROLOG) + sizeof(XML_PLIST_EPILOG) - 1; 539 size += sizeof(XML_PLIST_PROLOG) + sizeof(XML_PLIST_EPILOG) - 1;
526 540
527 strbuf_t *outbuf = str_buf_new(size); 541 strbuf_t *outbuf = str_buf_new(size);
542 if (!outbuf) {
543 PLIST_XML_WRITE_ERR("Could not allocate output buffer");
544 return PLIST_ERR_NO_MEM;
545 }
528 546
529 str_buf_append(outbuf, XML_PLIST_PROLOG, sizeof(XML_PLIST_PROLOG)-1); 547 str_buf_append(outbuf, XML_PLIST_PROLOG, sizeof(XML_PLIST_PROLOG)-1);
530 548
531 if (node_to_xml(plist, &outbuf, 0) < 0) { 549 res = node_to_xml(plist, &outbuf, 0);
550 if (res < 0) {
532 str_buf_free(outbuf); 551 str_buf_free(outbuf);
533 *plist_xml = NULL; 552 *plist_xml = NULL;
534 *length = 0; 553 *length = 0;
535 return; 554 return res;
536 } 555 }
537 556
538 str_buf_append(outbuf, XML_PLIST_EPILOG, sizeof(XML_PLIST_EPILOG)); 557 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)
542 561
543 outbuf->data = NULL; 562 outbuf->data = NULL;
544 str_buf_free(outbuf); 563 str_buf_free(outbuf);
564
565 return PLIST_ERR_SUCCESS;
545} 566}
546 567
547struct _parse_ctx { 568struct _parse_ctx {
@@ -932,8 +953,9 @@ static char* text_parts_get_content(text_part_t *tp, int unesc_entities, size_t
932 return str; 953 return str;
933} 954}
934 955
935static void node_from_xml(parse_ctx ctx, plist_t *plist) 956static int node_from_xml(parse_ctx ctx, plist_t *plist)
936{ 957{
958 int res;
937 char *tag = NULL; 959 char *tag = NULL;
938 char *keyname = NULL; 960 char *keyname = NULL;
939 plist_t subnode = NULL; 961 plist_t subnode = NULL;
@@ -1427,17 +1449,24 @@ err_out:
1427 if (ctx->err) { 1449 if (ctx->err) {
1428 plist_free(*plist); 1450 plist_free(*plist);
1429 *plist = NULL; 1451 *plist = NULL;
1452 res = PLIST_ERR_PARSE;
1453 } else {
1454 res = PLIST_ERR_SUCCESS;
1430 } 1455 }
1456 return res;
1431} 1457}
1432 1458
1433PLIST_API void plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist) 1459PLIST_API plist_err_t plist_from_xml(const char *plist_xml, uint32_t length, plist_t * plist)
1434{ 1460{
1461 if (!plist) {
1462 return PLIST_ERR_INVALID_ARG;
1463 }
1464 *plist = NULL;
1435 if (!plist_xml || (length == 0)) { 1465 if (!plist_xml || (length == 0)) {
1436 *plist = NULL; 1466 return PLIST_ERR_INVALID_ARG;
1437 return;
1438 } 1467 }
1439 1468
1440 struct _parse_ctx ctx = { plist_xml, plist_xml + length, 0 }; 1469 struct _parse_ctx ctx = { plist_xml, plist_xml + length, 0 };
1441 1470
1442 node_from_xml(&ctx, plist); 1471 return node_from_xml(&ctx, plist);
1443} 1472}