diff options
Diffstat (limited to 'src/bplist.c')
| -rw-r--r-- | src/bplist.c | 60 | 
1 files changed, 45 insertions, 15 deletions
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;  }  | 
