Add NULL checks across codebase
diff --git a/src/base64.c b/src/base64.c
index 76990b9..603ab6d 100644
--- a/src/base64.c
+++ b/src/base64.c
@@ -77,6 +77,7 @@
 	size_t len = (*size > 0) ? *size : strlen(buf);
 	if (len <= 0) return NULL;
 	unsigned char *outbuf = (unsigned char*)malloc((len/4)*3+3);
+	if (!outbuf) return NULL;
 	const char *ptr = buf;
 	size_t p = 0;
 	int wv, w1, w2, w3, w4;
diff --git a/src/bplist.c b/src/bplist.c
index f0c44fc..308b787 100644
--- a/src/bplist.c
+++ b/src/bplist.c
@@ -27,7 +27,6 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
 
 #include <ctype.h>
 #include <inttypes.h>
@@ -279,6 +278,10 @@
 static plist_t parse_int_node(const char **bnode, uint8_t size)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
 
     size = 1 << size;			// make length less misleading
     switch (size)
@@ -309,6 +312,10 @@
 static plist_t parse_real_node(const char **bnode, uint8_t size)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
 
     size = 1 << size;			// make length less misleading
     switch (size)
@@ -357,6 +364,10 @@
 static plist_t parse_string_node(const char **bnode, uint64_t size)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
 
     data->type = PLIST_STRING;
     data->strval = (char *) malloc(sizeof(char) * (size + 1));
@@ -446,6 +457,10 @@
 static plist_t parse_unicode_node(const char **bnode, uint64_t size)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     size_t items_read = 0;
     size_t items_written = 0;
 
@@ -463,11 +478,14 @@
 static plist_t parse_data_node(const char **bnode, uint64_t size)
 {
     plist_data_t data = plist_new_plist_data();
-
+    if (!data) {
+        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_DATA;
     data->length = size;
     data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size);
-    if (!data->strval) {
+    if (!data->buff) {
         plist_free_data(data);
         PLIST_BIN_ERR("%s: Could not allocate %" PRIu64 " bytes\n", __func__, sizeof(uint8_t) * size);
         return NULL;
@@ -483,6 +501,10 @@
     uint64_t str_i = 0, str_j = 0;
     uint64_t index1, index2;
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     const char *index1_ptr = NULL;
     const char *index2_ptr = NULL;
 
@@ -490,6 +512,11 @@
     data->length = size;
 
     plist_t node = node_create(NULL, data);
+    if (!node) {
+        plist_free_data(data);
+        PLIST_BIN_ERR("%s: failed to create node\n", __func__);
+        return NULL;
+    }
 
     for (j = 0; j < data->length; j++) {
         str_i = j * bplist->ref_size;
@@ -562,12 +589,21 @@
     uint64_t str_j = 0;
     uint64_t index1;
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     const char *index1_ptr = NULL;
 
     data->type = PLIST_ARRAY;
     data->length = size;
 
     plist_t node = node_create(NULL, data);
+    if (!node) {
+        plist_free_data(data);
+        PLIST_BIN_ERR("%s: failed to create node\n", __func__);
+        return NULL;
+    }
 
     for (j = 0; j < data->length; j++) {
         str_j = j * bplist->ref_size;
@@ -603,6 +639,10 @@
 static plist_t parse_uid_node(const char **bnode, uint8_t size)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     size = size + 1;
     data->intval = UINT_TO_HOST(*bnode, size);
     if (data->intval > UINT32_MAX) {
@@ -673,6 +713,10 @@
         case BPLIST_TRUE:
         {
             plist_data_t data = plist_new_plist_data();
+            if (!data) {
+                PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
+                return NULL;
+            }
             data->type = PLIST_BOOLEAN;
             data->boolval = TRUE;
             data->length = 1;
@@ -682,6 +726,10 @@
         case BPLIST_FALSE:
         {
             plist_data_t data = plist_new_plist_data();
+            if (!data) {
+                PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
+                return NULL;
+            }
             data->type = PLIST_BOOLEAN;
             data->boolval = FALSE;
             data->length = 1;
@@ -691,6 +739,10 @@
         case BPLIST_NULL:
         {
             plist_data_t data = plist_new_plist_data();
+            if (!data) {
+                PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
+                return NULL;
+            }
             data->type = PLIST_NULL;
             data->length = 0;
             return node_create(NULL, data);
@@ -1043,7 +1095,7 @@
 
     // insert new ref
     index_val = (uint64_t *) malloc(sizeof(uint64_t));
-    assert(index_val != NULL);
+    if (!index_val) return PLIST_ERR_NO_MEM;
     *index_val = ser->objects->len;
     hash_table_insert(ser->ref_table, node, index_val);
 
@@ -1461,7 +1513,9 @@
 
     //write objects and table
     offsets = (uint64_t *) malloc(num_objects * sizeof(uint64_t));
-    assert(offsets != NULL);
+    if (!offsets) {
+        return PLIST_ERR_NO_MEM;
+    }
     for (i = 0; i < num_objects; i++)
     {
 
diff --git a/src/jplist.c b/src/jplist.c
index 2c88756..2bb526e 100644
--- a/src/jplist.c
+++ b/src/jplist.c
@@ -540,6 +540,10 @@
         val = plist_new_bool(1);
     } else if (!strncmp("null", str_val, str_len)) {
         plist_data_t data = plist_new_plist_data();
+        if (!data) {
+            PLIST_JSON_ERR("%s: failed to allocate plist data\n", __func__);
+            return NULL;
+        }
         data->type = PLIST_NULL;
         val = plist_new_node(data);
     } else if (isdigit(str_val[0]) || (str_val[0] == '-' && str_val+1 < str_end && isdigit(str_val[1]))) {
@@ -598,6 +602,10 @@
     } else {
         PLIST_JSON_ERR("%s: invalid primitive value '%.*s' encountered\n", __func__, (int)str_len, str_val);
     }
+    if (!val) {
+        PLIST_JSON_ERR("%s: failed to create node\n", __func__);
+        return NULL;
+    }
     (*index)++;
     return val;
 }
@@ -695,10 +703,20 @@
     plist_t node;
 
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        free(strval);
+        PLIST_JSON_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_STRING;
     data->strval = strval;
     data->length = str_len;
     node = plist_new_node(data);
+    if (!node) {
+        plist_free_data(data);
+        PLIST_JSON_ERR("%s: failed to create node\n", __func__);
+        return NULL;
+    }
 
     (*index)++;
     return node;
diff --git a/src/plist.c b/src/plist.c
index ea285e0..22ef4d7 100644
--- a/src/plist.c
+++ b/src/plist.c
@@ -358,8 +358,7 @@
 
 plist_data_t plist_new_plist_data(void)
 {
-    plist_data_t data = (plist_data_t) calloc(1, sizeof(struct plist_data_s));
-    return data;
+    return (plist_data_t) calloc(1, sizeof(struct plist_data_s));
 }
 
 static unsigned int dict_key_hash(const void *data)
@@ -471,6 +470,10 @@
 plist_t plist_new_dict(void)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_DICT;
     return plist_new_node(data);
 }
@@ -478,6 +481,10 @@
 plist_t plist_new_array(void)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_ARRAY;
     return plist_new_node(data);
 }
@@ -486,24 +493,48 @@
 static plist_t plist_new_key(const char *val)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_KEY;
     data->strval = strdup(val);
-    data->length = strlen(val);
+    if (!data->strval) {
+        plist_free_data(data);
+        PLIST_ERR("%s: strdup failed\n", __func__);
+        return NULL;
+    } else {
+        data->length = strlen(val);
+    }
     return plist_new_node(data);
 }
 
 plist_t plist_new_string(const char *val)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_STRING;
     data->strval = strdup(val);
-    data->length = strlen(val);
+    if (!data->strval) {
+        plist_free_data(data);
+        PLIST_ERR("%s: strdup failed\n", __func__);
+        return NULL;
+    } else {
+        data->length = strlen(val);
+    }
     return plist_new_node(data);
 }
 
 plist_t plist_new_bool(uint8_t val)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_BOOLEAN;
     data->boolval = val;
     data->length = sizeof(uint8_t);
@@ -513,6 +544,10 @@
 plist_t plist_new_uint(uint64_t val)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_INT;
     data->intval = val;
     data->length = (val > INT_MAX) ? sizeof(uint64_t)*2 : sizeof(uint64_t);
@@ -522,6 +557,10 @@
 plist_t plist_new_int(int64_t val)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_INT;
     data->intval = val;
     data->length = sizeof(uint64_t);
@@ -531,6 +570,10 @@
 plist_t plist_new_uid(uint64_t val)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_UID;
     data->intval = val;
     data->length = sizeof(uint64_t);
@@ -540,6 +583,10 @@
 plist_t plist_new_real(double val)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_REAL;
     data->realval = val;
     data->length = sizeof(double);
@@ -549,11 +596,19 @@
 plist_t plist_new_data(const char *val, uint64_t length)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_DATA;
-if (val && length) {
-    data->buff = (uint8_t *) malloc(length);
-    memcpy(data->buff, val, length);
-}
+    if (val && length) {
+        data->buff = (uint8_t *) malloc(length);
+        if (!data->buff) {
+            PLIST_ERR("%s: failed to allocate %" PRIu64 " bytes\n", __func__, length);
+            return NULL;
+        }
+        memcpy(data->buff, val, length);
+    }
     data->length = length;
     return plist_new_node(data);
 }
@@ -561,6 +616,10 @@
 plist_t plist_new_date(int32_t sec, int32_t usec)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_DATE;
     data->realval = (double)sec + (double)usec / 1000000;
     data->length = sizeof(double);
@@ -570,6 +629,10 @@
 plist_t plist_new_unix_date(int64_t sec)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_DATE;
     data->realval = (double)sec - MAC_EPOCH;
     data->length = sizeof(double);
@@ -579,6 +642,10 @@
 plist_t plist_new_null(void)
 {
     plist_data_t data = plist_new_plist_data();
+    if (!data) {
+        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
+        return NULL;
+    }
     data->type = PLIST_NULL;
     data->intval = 0;
     data->length = 0;
@@ -1128,7 +1195,6 @@
         return NULL;
     }
     plist_data_t data = plist_get_data(node);
-    assert(data);
     if (!data) {
         PLIST_ERR("%s: invalid node\n", __func__);
         return NULL;
@@ -1187,7 +1253,10 @@
             PLIST_ERR("%s: corrupt dict (value without key)\n", __func__);
             return;
         }
-        assert(PLIST_IS_KEY((plist_t)old_key));
+        if (!PLIST_IS_KEY((plist_t)old_key)) {
+            PLIST_ERR("%s: corrupt dict ('key' node is not PLIST_KEY\n", __func__);
+            return;
+        }
 
         // detach old value (do NOT free yet)
         int idx = node_detach((node_t)node, old_val);
@@ -1525,10 +1594,11 @@
 {
     plist_data_t data = NULL;
 
-    if (!node)
+    if (!node || !type || !value || !length)
         return;
 
     data = plist_get_data(node);
+    if (!data) return;
 
     *type = data->type;
     *length = data->length;
@@ -1549,9 +1619,17 @@
     case PLIST_KEY:
     case PLIST_STRING:
         *((char **) value) = strdup(data->strval);
+        if (!*((char **) value)) {
+            PLIST_ERR("%s: strdup failed\n", __func__);
+            return;
+        }
         break;
     case PLIST_DATA:
         *((uint8_t **) value) = (uint8_t *) malloc(*length * sizeof(uint8_t));
+        if (!*((uint8_t **) value)) {
+            PLIST_ERR("%s: malloc failed\n", __func__);
+            return;
+        }
         memcpy(*((uint8_t **) value), data->buff, *length * sizeof(uint8_t));
         break;
     case PLIST_ARRAY:
@@ -1789,11 +1867,14 @@
     return plist_data_compare(node_l, node_r);
 }
 
-static void plist_set_element_val(plist_t node, plist_type type, const void *value, uint64_t length)
+static plist_err_t plist_set_element_val(plist_t node, plist_type type, const void *value, uint64_t length)
 {
     //free previous allocated buffer
     plist_data_t data = plist_get_data(node);
-    assert(data);				// a node should always have data attached
+    if (!data) { // a node should always have data attached
+        PLIST_ERR("%s: Failed to allocate plist data\n", __func__);
+        return PLIST_ERR_NO_MEM;
+    }
 
     switch (data->type)
     {
@@ -1831,9 +1912,17 @@
     case PLIST_KEY:
     case PLIST_STRING:
         data->strval = strdup((char *) value);
+        if (!data->strval) {
+            PLIST_ERR("%s: strdup failed\n", __func__);
+            return PLIST_ERR_NO_MEM;
+        }
         break;
     case PLIST_DATA:
         data->buff = (uint8_t *) malloc(length);
+        if (!data->buff) {
+            PLIST_ERR("%s: malloc failed\n", __func__);
+            return PLIST_ERR_NO_MEM;
+        }
         memcpy(data->buff, value, length);
         break;
     case PLIST_ARRAY:
@@ -1841,6 +1930,7 @@
     default:
         break;
     }
+    return PLIST_ERR_SUCCESS;
 }
 
 void plist_set_key_val(plist_t node, const char *val)
diff --git a/src/xplist.c b/src/xplist.c
index 6100afc..73e2b9f 100644
--- a/src/xplist.c
+++ b/src/xplist.c
@@ -1216,7 +1216,17 @@
                 goto handle_closing;
             }
             plist_data_t data = plist_new_plist_data();
+            if (!data) {
+                PLIST_XML_ERR("failed to allocate plist data\n");
+                ctx->err = PLIST_ERR_NO_MEM;
+                goto err_out;
+            }
             subnode = plist_new_node(data);
+            if (!subnode) {
+                PLIST_XML_ERR("failed to create node\n");
+                ctx->err = PLIST_ERR_NO_MEM;
+                goto err_out;
+            }
 
             if (!strcmp(tag, XPLIST_DICT)) {
                 data->type = PLIST_DICT;
@@ -1425,6 +1435,12 @@
                         size_t size = tp->length;
                         if (size > 0) {
                             data->buff = base64decode(str_content, &size);
+                            if (!data->buff) {
+                                text_parts_free((text_part_t*)first_part.next);
+                                PLIST_XML_ERR("failed to decode base64 stream\n");
+                                ctx->err = PLIST_ERR_NO_MEM;
+                                goto err_out;
+                            }
                             data->length = size;
                         }