LLVMFuzzerTestOneInput:
   26|  2.39k|{
   27|  2.39k|	plist_t root_node = NULL;
   28|  2.39k|	plist_from_bin(reinterpret_cast<const char*>(data), size, &root_node);
   29|  2.39k|	plist_free(root_node);
   30|       |
   31|  2.39k|	return 0;
   32|  2.39k|}

node_destroy:
   31|   217k|{
   32|   217k|	if(!node) return;
  ------------------
  |  Branch (32:5): [True: 0, False: 217k]
  ------------------
   33|       |
   34|   217k|	if (node->children && node->children->count > 0) {
  ------------------
  |  Branch (34:6): [True: 17.9k, False: 199k]
  |  Branch (34:24): [True: 0, False: 17.9k]
  ------------------
   35|      0|		node_t ch;
   36|      0|		while ((ch = node->children->begin)) {
  ------------------
  |  Branch (36:10): [True: 0, False: 0]
  ------------------
   37|      0|			node_list_remove(node->children, ch);
   38|      0|			node_destroy(ch);
   39|      0|		}
   40|      0|	}
   41|   217k|	node_list_destroy(node->children);
   42|   217k|	node->children = NULL;
   43|       |
   44|   217k|	free(node);
   45|   217k|}
node_create:
   48|   217k|{
   49|   217k|	int error = 0;
   50|       |
   51|   217k|	node_t node = (node_t)calloc(1, sizeof(struct node));
   52|   217k|	if (node == NULL) {
  ------------------
  |  Branch (52:6): [True: 0, False: 217k]
  ------------------
   53|      0|		return NULL;
   54|      0|	}
   55|       |
   56|   217k|	node->data = data;
   57|   217k|	node->next = NULL;
   58|   217k|	node->prev = NULL;
   59|   217k|	node->count = 0;
   60|   217k|	node->parent = NULL;
   61|   217k|	node->children = NULL;
   62|       |
   63|       |	// Pass NULL to create a root node
   64|   217k|	if (parent != NULL) {
  ------------------
  |  Branch (64:6): [True: 0, False: 217k]
  ------------------
   65|       |		// This is a child node so attach it to it's parent
   66|      0|		error = node_attach(parent, node);
   67|      0|		if (error < 0) {
  ------------------
  |  Branch (67:7): [True: 0, False: 0]
  ------------------
   68|       |			// Unable to attach nodes
   69|      0|			node_destroy(node);
   70|      0|			return NULL;
   71|      0|		}
   72|      0|	}
   73|       |
   74|   217k|	return node;
   75|   217k|}
node_attach:
  133|   214k|{
  134|   214k|	if (!parent || !child) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (134:6): [True: 0, False: 214k]
  |  Branch (134:17): [True: 0, False: 214k]
  ------------------
  135|       |
  136|       |	// already parented?
  137|   214k|	if (child->parent) return NODE_ERR_PARENT;
  ------------------
  |  |   39|      0|#define NODE_ERR_PARENT       -3
  ------------------
  |  Branch (137:6): [True: 0, False: 214k]
  ------------------
  138|       |
  139|       |	// self/cycle guard
  140|   214k|	if (parent == child) return NODE_ERR_CIRCULAR_REF;
  ------------------
  |  |   40|      0|#define NODE_ERR_CIRCULAR_REF -4
  ------------------
  |  Branch (140:6): [True: 0, False: 214k]
  ------------------
  141|   214k|	if (would_create_cycle(parent, child)) return NODE_ERR_CIRCULAR_REF;
  ------------------
  |  |   40|      0|#define NODE_ERR_CIRCULAR_REF -4
  ------------------
  |  Branch (141:6): [True: 0, False: 214k]
  ------------------
  142|       |
  143|       |	// depth guard: depth(parent)+1+max_depth(child_subtree) <= NODE_MAX_DEPTH
  144|   214k|	int pd = node_depth_from_root(parent);
  145|   214k|	int cd = node_subtree_max_depth(child);
  146|   214k|	if (pd + 1 + cd > NODE_MAX_DEPTH) {
  ------------------
  |  |   33|   214k|#define NODE_MAX_DEPTH 512
  ------------------
  |  Branch (146:6): [True: 0, False: 214k]
  ------------------
  147|      0|		return NODE_ERR_MAX_DEPTH;
  ------------------
  |  |   41|      0|#define NODE_ERR_MAX_DEPTH    -5
  ------------------
  148|      0|	}
  149|       |
  150|   214k|	if (!parent->children) {
  ------------------
  |  Branch (150:6): [True: 17.9k, False: 196k]
  ------------------
  151|  17.9k|		parent->children = node_list_create();
  152|  17.9k|		if (!parent->children) return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  |  Branch (152:7): [True: 0, False: 17.9k]
  ------------------
  153|  17.9k|	}
  154|   214k|	int res = node_list_add(parent->children, child);
  155|   214k|	if (res == 0) {
  ------------------
  |  Branch (155:6): [True: 214k, False: 0]
  ------------------
  156|   214k|		child->parent = parent;
  157|   214k|		parent->count++;
  158|   214k|	}
  159|   214k|	return res;
  160|   214k|}
node_detach:
  163|   214k|{
  164|   214k|	if (!parent || !child) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (164:6): [True: 0, False: 214k]
  |  Branch (164:17): [True: 0, False: 214k]
  ------------------
  165|   214k|	if (!parent->children) return NODE_ERR_NOT_FOUND;
  ------------------
  |  |   42|      0|#define NODE_ERR_NOT_FOUND    -6
  ------------------
  |  Branch (165:6): [True: 0, False: 214k]
  ------------------
  166|   214k|	if (child->parent && child->parent != parent) return NODE_ERR_PARENT;
  ------------------
  |  |   39|      0|#define NODE_ERR_PARENT       -3
  ------------------
  |  Branch (166:6): [True: 214k, False: 0]
  |  Branch (166:23): [True: 0, False: 214k]
  ------------------
  167|       |
  168|   214k|	int node_index = node_list_remove(parent->children, child);
  169|   214k|	if (node_index >= 0) {
  ------------------
  |  Branch (169:6): [True: 214k, False: 0]
  ------------------
  170|   214k|		if (parent->count > 0) parent->count--;
  ------------------
  |  Branch (170:7): [True: 214k, False: 0]
  ------------------
  171|   214k|		child->parent = NULL;
  172|   214k|		child->prev = NULL;
  173|       |		child->next = NULL;
  174|   214k|	}
  175|   214k|	return node_index;
  176|   214k|}
node_first_child:
  262|   532k|{
  263|   532k|	if (!node || !node->children) return NULL;
  ------------------
  |  Branch (263:6): [True: 0, False: 532k]
  |  Branch (263:15): [True: 199k, False: 332k]
  ------------------
  264|   332k|	return node->children->begin;
  265|   532k|}
node_next_sibling:
  274|  1.27M|{
  275|  1.27M|	if (!node) return NULL;
  ------------------
  |  Branch (275:6): [True: 0, False: 1.27M]
  ------------------
  276|  1.27M|	return node->next;
  277|  1.27M|}
node.c:would_create_cycle:
  124|   214k|{
  125|       |	// if parent is anywhere in child's ancestor chain => cycle
  126|   429k|	for (node_t p = parent; p; p = p->parent) {
  ------------------
  |  Branch (126:26): [True: 214k, False: 214k]
  ------------------
  127|   214k|		if (p == child) return 1;
  ------------------
  |  Branch (127:7): [True: 0, False: 214k]
  ------------------
  128|   214k|	}
  129|   214k|	return 0;
  130|   214k|}
node.c:node_depth_from_root:
   78|   214k|{
   79|   214k|	int d = 0;
   80|   214k|	while (n && n->parent) {
  ------------------
  |  Branch (80:9): [True: 214k, False: 0]
  |  Branch (80:14): [True: 0, False: 214k]
  ------------------
   81|      0|		d++;
   82|      0|		n = n->parent;
   83|      0|		if (d > NODE_MAX_DEPTH) return d; // early out
  ------------------
  |  |   33|      0|#define NODE_MAX_DEPTH 512
  ------------------
  |  Branch (83:7): [True: 0, False: 0]
  ------------------
   84|      0|	}
   85|   214k|	return d;
   86|   214k|}
node.c:node_subtree_max_depth:
   89|   214k|{
   90|   214k|	if (!root) return 0;
  ------------------
  |  Branch (90:6): [True: 0, False: 214k]
  ------------------
   91|       |
   92|   214k|	typedef struct { node_t n; int depth; } frame_t;
   93|   214k|	size_t cap = 64, sp = 0;
   94|   214k|	frame_t *st = (frame_t*)malloc(cap * sizeof(*st));
   95|   214k|	if (!st) return NODE_MAX_DEPTH + 1;
  ------------------
  |  |   33|      0|#define NODE_MAX_DEPTH 512
  ------------------
  |  Branch (95:6): [True: 0, False: 214k]
  ------------------
   96|       |
   97|   214k|	st[sp++] = (frame_t){ root, 0 };
   98|   214k|	int maxd = 0;
   99|       |
  100|  1.70M|	while (sp) {
  ------------------
  |  Branch (100:9): [True: 1.48M, False: 214k]
  ------------------
  101|  1.48M|		frame_t f = st[--sp];
  102|  1.48M|		if (f.depth > maxd) maxd = f.depth;
  ------------------
  |  Branch (102:7): [True: 33.8k, False: 1.45M]
  ------------------
  103|  1.48M|		if (maxd > NODE_MAX_DEPTH) break;
  ------------------
  |  |   33|  1.48M|#define NODE_MAX_DEPTH 512
  ------------------
  |  Branch (103:7): [True: 0, False: 1.48M]
  ------------------
  104|       |
  105|  1.48M|		if (!f.n->children) continue;
  ------------------
  |  Branch (105:7): [True: 1.39M, False: 98.8k]
  ------------------
  106|       |
  107|  1.37M|		for (node_t ch = node_first_child(f.n); ch; ch = node_next_sibling(ch)) {
  ------------------
  |  Branch (107:43): [True: 1.27M, False: 98.8k]
  ------------------
  108|  1.27M|			if (sp == cap) {
  ------------------
  |  Branch (108:8): [True: 904, False: 1.27M]
  ------------------
  109|    904|				cap *= 2;
  110|    904|				frame_t *tmp = (frame_t*)realloc(st, cap * sizeof(*st));
  111|    904|				if (!tmp) { maxd = NODE_MAX_DEPTH + 1; goto out; }
  ------------------
  |  |   33|      0|#define NODE_MAX_DEPTH 512
  ------------------
  |  Branch (111:9): [True: 0, False: 904]
  ------------------
  112|    904|				st = tmp;
  113|    904|			}
  114|  1.27M|			st[sp++] = (frame_t){ ch, f.depth + 1 };
  115|  1.27M|		}
  116|  98.8k|	}
  117|       |
  118|   214k|out:
  119|   214k|	free(st);
  120|   214k|	return maxd;
  121|   214k|}

node_list_destroy:
   32|   217k|{
   33|   217k|	free(list);
   34|   217k|}
node_list_create:
   37|  17.9k|{
   38|  17.9k|	node_list_t list = (node_list_t)calloc(1, sizeof(struct node_list));
   39|  17.9k|	if (list == NULL) {
  ------------------
  |  Branch (39:6): [True: 0, False: 17.9k]
  ------------------
   40|      0|		return NULL;
   41|      0|	}
   42|       |
   43|       |	// Initialize structure
   44|  17.9k|	list->begin = NULL;
   45|       |	list->end = NULL;
   46|  17.9k|	list->count = 0;
   47|  17.9k|	return list;
   48|  17.9k|}
node_list_add:
   51|   214k|{
   52|   214k|	if (!list || !node) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (52:6): [True: 0, False: 214k]
  |  Branch (52:15): [True: 0, False: 214k]
  ------------------
   53|       |
   54|       |	// Find the last element in the list
   55|   214k|	node_t last = list->end;
   56|       |
   57|       |	// Setup our new node as the new last element
   58|   214k|	node->next = NULL;
   59|   214k|	node->prev = last;
   60|       |
   61|       |	// Set the next element of our old "last" element
   62|   214k|	if (last) {
  ------------------
  |  Branch (62:6): [True: 196k, False: 17.9k]
  ------------------
   63|       |		// but only if the node list is not empty
   64|   196k|		last->next = node;
   65|   196k|	} else {
   66|       |		// otherwise this is the start of the list
   67|  17.9k|		list->begin = node;
   68|  17.9k|	}
   69|       |
   70|       |	// Set the lists prev to the new last element
   71|   214k|	list->end = node;
   72|       |
   73|       |	// Increment our node count for this list
   74|   214k|	list->count++;
   75|   214k|	return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|   214k|#define NODE_ERR_SUCCESS       0
  ------------------
   76|   214k|}
node_list_remove:
  120|   214k|{
  121|   214k|	if (!list || !node) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (121:6): [True: 0, False: 214k]
  |  Branch (121:15): [True: 0, False: 214k]
  ------------------
  122|   214k|	if (list->count == 0) return NODE_ERR_NOT_FOUND;
  ------------------
  |  |   42|      0|#define NODE_ERR_NOT_FOUND    -6
  ------------------
  |  Branch (122:6): [True: 0, False: 214k]
  ------------------
  123|       |
  124|   214k|	int node_index = 0;
  125|   214k|	for (node_t n = list->begin; n; n = n->next, node_index++) {
  ------------------
  |  Branch (125:31): [True: 214k, False: 0]
  ------------------
  126|   214k|		if (node != n) continue;
  ------------------
  |  Branch (126:7): [True: 0, False: 214k]
  ------------------
  127|       |
  128|   214k|		node_t newnode = node->next;
  129|   214k|		if (node->prev) {
  ------------------
  |  Branch (129:7): [True: 0, False: 214k]
  ------------------
  130|      0|			node->prev->next = newnode;
  131|   214k|		} else {
  132|       |			// we just removed the first element
  133|   214k|			list->begin = newnode;
  134|   214k|		}
  135|       |
  136|   214k|		if (newnode) {
  ------------------
  |  Branch (136:7): [True: 196k, False: 17.9k]
  ------------------
  137|   196k|			newnode->prev = node->prev;
  138|   196k|		} else {
  139|       |			// we removed the last element, set new end
  140|  17.9k|			list->end = node->prev;
  141|  17.9k|		}
  142|       |
  143|       |		// fully detach node from list
  144|   214k|		node->prev = NULL;
  145|   214k|		node->next = NULL;
  146|       |
  147|   214k|		list->count--;
  148|   214k|		return node_index;
  149|   214k|	}
  150|      0|	return NODE_ERR_NOT_FOUND;
  ------------------
  |  |   42|      0|#define NODE_ERR_NOT_FOUND    -6
  ------------------
  151|   214k|}

plist_bin_init:
  254|      2|{
  255|       |    /* init binary plist stuff */
  256|      2|#ifdef DEBUG
  257|      2|    char *env_debug = getenv("PLIST_BIN_DEBUG");
  258|      2|    if (env_debug && !strcmp(env_debug, "1")) {
  ------------------
  |  Branch (258:9): [True: 0, False: 2]
  |  Branch (258:22): [True: 0, False: 0]
  ------------------
  259|      0|        plist_bin_debug = 1;
  260|      0|    }
  261|      2|#endif
  262|      2|}
plist_from_bin:
  906|  2.39k|{
  907|  2.39k|    bplist_trailer_t *trailer = NULL;
  908|  2.39k|    uint8_t offset_size = 0;
  909|  2.39k|    uint8_t ref_size = 0;
  910|  2.39k|    uint64_t num_objects = 0;
  911|  2.39k|    uint64_t root_object = 0;
  912|  2.39k|    const char *offset_table = NULL;
  913|  2.39k|    uint64_t offset_table_size = 0;
  914|  2.39k|    const char *start_data = NULL;
  915|  2.39k|    const char *end_data = NULL;
  916|       |
  917|  2.39k|    if (!plist) {
  ------------------
  |  Branch (917:9): [True: 0, False: 2.39k]
  ------------------
  918|      0|        return PLIST_ERR_INVALID_ARG;
  919|      0|    }
  920|  2.39k|    *plist = NULL;
  921|  2.39k|    if (!plist_bin || length == 0) {
  ------------------
  |  Branch (921:9): [True: 0, False: 2.39k]
  |  Branch (921:23): [True: 0, False: 2.39k]
  ------------------
  922|      0|        return PLIST_ERR_INVALID_ARG;
  923|      0|    }
  924|       |
  925|       |    //first check we have enough data
  926|  2.39k|    if (!(length >= BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE + sizeof(bplist_trailer_t))) {
  ------------------
  |  |   44|  2.39k|#define BPLIST_MAGIC_SIZE       6
  ------------------
                  if (!(length >= BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE + sizeof(bplist_trailer_t))) {
  ------------------
  |  |   47|  2.39k|#define BPLIST_VERSION_SIZE     2
  ------------------
  |  Branch (926:9): [True: 12, False: 2.38k]
  ------------------
  927|     12|        PLIST_BIN_ERR("plist data is to small to hold a binary plist\n");
  ------------------
  |  |  246|     12|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 12]
  |  |  ------------------
  ------------------
  928|     12|        return PLIST_ERR_PARSE;
  929|     12|    }
  930|       |    //check that plist_bin in actually a plist
  931|  2.38k|    if (memcmp(plist_bin, BPLIST_MAGIC, BPLIST_MAGIC_SIZE) != 0) {
  ------------------
  |  |   43|  2.38k|#define BPLIST_MAGIC            ((uint8_t*)"bplist")
  ------------------
                  if (memcmp(plist_bin, BPLIST_MAGIC, BPLIST_MAGIC_SIZE) != 0) {
  ------------------
  |  |   44|  2.38k|#define BPLIST_MAGIC_SIZE       6
  ------------------
  |  Branch (931:9): [True: 35, False: 2.34k]
  ------------------
  932|     35|        PLIST_BIN_ERR("bplist magic mismatch\n");
  ------------------
  |  |  246|     35|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 35]
  |  |  ------------------
  ------------------
  933|     35|        return PLIST_ERR_PARSE;
  934|     35|    }
  935|       |    //check for known version
  936|  2.34k|    if (memcmp(plist_bin + BPLIST_MAGIC_SIZE, BPLIST_VERSION, BPLIST_VERSION_SIZE) != 0) {
  ------------------
  |  |   44|  2.34k|#define BPLIST_MAGIC_SIZE       6
  ------------------
                  if (memcmp(plist_bin + BPLIST_MAGIC_SIZE, BPLIST_VERSION, BPLIST_VERSION_SIZE) != 0) {
  ------------------
  |  |   46|  2.34k|#define BPLIST_VERSION          ((uint8_t*)"00")
  ------------------
                  if (memcmp(plist_bin + BPLIST_MAGIC_SIZE, BPLIST_VERSION, BPLIST_VERSION_SIZE) != 0) {
  ------------------
  |  |   47|  2.34k|#define BPLIST_VERSION_SIZE     2
  ------------------
  |  Branch (936:9): [True: 38, False: 2.31k]
  ------------------
  937|     38|        PLIST_BIN_ERR("unsupported binary plist version '%.2s\n", plist_bin+BPLIST_MAGIC_SIZE);
  ------------------
  |  |  246|     38|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 38]
  |  |  ------------------
  ------------------
  938|     38|        return PLIST_ERR_PARSE;
  939|     38|    }
  940|       |
  941|  2.31k|    start_data = plist_bin + BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE;
  ------------------
  |  |   44|  2.31k|#define BPLIST_MAGIC_SIZE       6
  ------------------
                  start_data = plist_bin + BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE;
  ------------------
  |  |   47|  2.31k|#define BPLIST_VERSION_SIZE     2
  ------------------
  942|  2.31k|    end_data = plist_bin + length - sizeof(bplist_trailer_t);
  943|       |
  944|       |    //now parse trailer
  945|  2.31k|    trailer = (bplist_trailer_t*)end_data;
  946|       |
  947|  2.31k|    offset_size = trailer->offset_size;
  948|  2.31k|    ref_size = trailer->ref_size;
  949|  2.31k|    num_objects = be64toh(trailer->num_objects);
  950|  2.31k|    root_object = be64toh(trailer->root_object_index);
  951|       |
  952|  2.31k|    uint64_t offset_table_offset = be64toh(trailer->offset_table_offset);
  953|  2.31k|    uint64_t max_valid_offset = (uint64_t)length - sizeof(bplist_trailer_t);
  954|  2.31k|    if (offset_table_offset > max_valid_offset) {
  ------------------
  |  Branch (954:9): [True: 112, False: 2.19k]
  ------------------
  955|    112|        PLIST_BIN_ERR("offset table offset outside of valid range\n");
  ------------------
  |  |  246|    112|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 112]
  |  |  ------------------
  ------------------
  956|    112|        return PLIST_ERR_PARSE;
  957|    112|    }
  958|  2.19k|    offset_table = (char *)(plist_bin + offset_table_offset);
  959|       |
  960|  2.19k|    if (num_objects == 0) {
  ------------------
  |  Branch (960:9): [True: 1, False: 2.19k]
  ------------------
  961|      1|        PLIST_BIN_ERR("number of objects must be larger than 0\n");
  ------------------
  |  |  246|      1|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 1]
  |  |  ------------------
  ------------------
  962|      1|        return PLIST_ERR_PARSE;
  963|      1|    }
  964|       |
  965|  2.19k|    if (offset_size == 0) {
  ------------------
  |  Branch (965:9): [True: 14, False: 2.18k]
  ------------------
  966|     14|        PLIST_BIN_ERR("offset size in trailer must be larger than 0\n");
  ------------------
  |  |  246|     14|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 14]
  |  |  ------------------
  ------------------
  967|     14|        return PLIST_ERR_PARSE;
  968|     14|    }
  969|       |
  970|  2.18k|    if (ref_size == 0) {
  ------------------
  |  Branch (970:9): [True: 7, False: 2.17k]
  ------------------
  971|      7|        PLIST_BIN_ERR("object reference size in trailer must be larger than 0\n");
  ------------------
  |  |  246|      7|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 7]
  |  |  ------------------
  ------------------
  972|      7|        return PLIST_ERR_PARSE;
  973|      7|    }
  974|       |
  975|  2.17k|    if (root_object >= num_objects) {
  ------------------
  |  Branch (975:9): [True: 86, False: 2.09k]
  ------------------
  976|     86|        PLIST_BIN_ERR("root object index (%" PRIu64 ") must be smaller than number of objects (%" PRIu64 ")\n", root_object, num_objects);
  ------------------
  |  |  246|     86|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 86]
  |  |  ------------------
  ------------------
  977|     86|        return PLIST_ERR_PARSE;
  978|     86|    }
  979|       |
  980|  2.09k|    if (offset_table < start_data || offset_table >= end_data) {
  ------------------
  |  Branch (980:9): [True: 50, False: 2.04k]
  |  Branch (980:38): [True: 29, False: 2.01k]
  ------------------
  981|     79|        PLIST_BIN_ERR("offset table offset points outside of valid range\n");
  ------------------
  |  |  246|     79|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 79]
  |  |  ------------------
  ------------------
  982|     79|        return PLIST_ERR_PARSE;
  983|     79|    }
  984|       |
  985|  2.01k|    if (uint64_mul_overflow(num_objects, offset_size, &offset_table_size)) {
  ------------------
  |  |  221|  2.01k|#define uint64_mul_overflow(a, b, r) __builtin_umulll_overflow(a, b, (unsigned long long*)(r))
  |  |  ------------------
  |  |  |  Branch (221:38): [True: 5, False: 2.00k]
  |  |  ------------------
  ------------------
  986|      5|        PLIST_BIN_ERR("integer overflow when calculating offset table size\n");
  ------------------
  |  |  246|      5|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 5]
  |  |  ------------------
  ------------------
  987|      5|        return PLIST_ERR_PARSE;
  988|      5|    }
  989|       |
  990|  2.00k|    if (offset_table_size > (uint64_t)(end_data - offset_table)) {
  ------------------
  |  Branch (990:9): [True: 111, False: 1.89k]
  ------------------
  991|    111|        PLIST_BIN_ERR("offset table points outside of valid range\n");
  ------------------
  |  |  246|    111|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 111]
  |  |  ------------------
  ------------------
  992|    111|        return PLIST_ERR_PARSE;
  993|    111|    }
  994|       |
  995|  1.89k|    struct bplist_data bplist;
  996|  1.89k|    bplist.data = plist_bin;
  997|  1.89k|    bplist.size = length;
  998|  1.89k|    bplist.num_objects = num_objects;
  999|  1.89k|    bplist.ref_size = ref_size;
 1000|  1.89k|    bplist.offset_size = offset_size;
 1001|  1.89k|    bplist.offset_table = offset_table;
 1002|  1.89k|    bplist.level = 0;
 1003|  1.89k|    bplist.used_indexes = ptr_array_new(16);
 1004|  1.89k|    bplist.err = PLIST_ERR_SUCCESS;
 1005|       |
 1006|  1.89k|    if (!bplist.used_indexes) {
  ------------------
  |  Branch (1006:9): [True: 0, False: 1.89k]
  ------------------
 1007|      0|        PLIST_BIN_ERR("failed to create array to hold used node indexes. Out of memory?\n");
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1008|      0|        return PLIST_ERR_NO_MEM;
 1009|      0|    }
 1010|       |
 1011|  1.89k|    *plist = parse_bin_node_at_index(&bplist, root_object);
 1012|       |
 1013|  1.89k|    ptr_array_free(bplist.used_indexes);
 1014|       |
 1015|  1.89k|    if (!*plist) {
  ------------------
  |  Branch (1015:9): [True: 1.69k, False: 203]
  ------------------
 1016|  1.69k|        return (bplist.err != PLIST_ERR_SUCCESS) ? bplist.err : PLIST_ERR_PARSE;
  ------------------
  |  Branch (1016:16): [True: 443, False: 1.24k]
  ------------------
 1017|  1.69k|    }
 1018|       |
 1019|    203|    return PLIST_ERR_SUCCESS;
 1020|  1.89k|}
bplist.c:parse_bin_node_at_index:
  835|   218k|{
  836|   218k|    int i = 0;
  837|   218k|    const char* ptr = NULL;
  838|   218k|    plist_t plist = NULL;
  839|   218k|    const char* idx_ptr = NULL;
  840|       |
  841|   218k|    if (node_index >= bplist->num_objects) {
  ------------------
  |  Branch (841:9): [True: 0, False: 218k]
  ------------------
  842|      0|        PLIST_BIN_ERR("node index (%u) must be smaller than the number of objects (%" PRIu64 ")\n", node_index, bplist->num_objects);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  843|      0|        bplist->err = PLIST_ERR_PARSE;
  844|      0|        return NULL;
  845|      0|    }
  846|       |
  847|   218k|    idx_ptr = bplist->offset_table + node_index * bplist->offset_size;
  848|   218k|    if (idx_ptr < bplist->offset_table ||
  ------------------
  |  Branch (848:9): [True: 0, False: 218k]
  ------------------
  849|   218k|        idx_ptr >= bplist->offset_table + bplist->num_objects * bplist->offset_size) {
  ------------------
  |  Branch (849:9): [True: 0, False: 218k]
  ------------------
  850|      0|        PLIST_BIN_ERR("node index %u points outside of valid range\n", node_index);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  851|      0|        bplist->err = PLIST_ERR_PARSE;
  852|      0|        return NULL;
  853|      0|    }
  854|       |
  855|   218k|    uint64_t node_offset = UINT_TO_HOST(idx_ptr, bplist->offset_size);
  ------------------
  |  |  187|   218k|	({ \
  |  |  188|   218k|		union plist_uint_ptr __up; \
  |  |  189|   218k|		__up.src = ((n) > 8) ? (const char*)(x) + ((n) - 8) : (const char*)(x); \
  |  |  ------------------
  |  |  |  Branch (189:14): [True: 220, False: 218k]
  |  |  ------------------
  |  |  190|   218k|		((n) >= 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (190:4): [True: 446, False: 218k]
  |  |  ------------------
  |  |  191|   218k|		((n) == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (191:4): [True: 214, False: 218k]
  |  |  ------------------
  |  |  192|   218k|		((n) == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (192:4): [True: 345, False: 217k]
  |  |  ------------------
  |  |  193|   218k|		((n) == 1 ? *__up.u8ptr : \
  |  |  ------------------
  |  |  |  Branch (193:4): [True: 217k, False: 249]
  |  |  ------------------
  |  |  194|   217k|		beNtoh( get_unaligned(__up.u64ptr), n) \
  |  |  ------------------
  |  |  |  |  170|   217k|#define beNtoh(x,n) be64toh((x) << ((8-(n)) << 3))
  |  |  ------------------
  |  |  195|   217k|		)))); \
  |  |  196|   218k|	})
  ------------------
  856|   218k|    if (node_offset > (uint64_t)bplist->size) {
  ------------------
  |  Branch (856:9): [True: 127, False: 218k]
  ------------------
  857|    127|        PLIST_BIN_ERR("node offset overflow (%" PRIu64 ")\n", node_offset);
  ------------------
  |  |  246|    127|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 127]
  |  |  ------------------
  ------------------
  858|    127|        bplist->err = PLIST_ERR_PARSE;
  859|    127|        return NULL;
  860|    127|    }
  861|   218k|    ptr = bplist->data + node_offset;
  862|       |    /* make sure the node offset is in a sane range */
  863|   218k|    if ((ptr < bplist->data+BPLIST_MAGIC_SIZE+BPLIST_VERSION_SIZE) || (ptr >= bplist->offset_table)) {
  ------------------
  |  |   44|   218k|#define BPLIST_MAGIC_SIZE       6
  ------------------
                  if ((ptr < bplist->data+BPLIST_MAGIC_SIZE+BPLIST_VERSION_SIZE) || (ptr >= bplist->offset_table)) {
  ------------------
  |  |   47|   218k|#define BPLIST_VERSION_SIZE     2
  ------------------
  |  Branch (863:9): [True: 9, False: 218k]
  |  Branch (863:71): [True: 23, False: 218k]
  ------------------
  864|     32|        PLIST_BIN_ERR("offset for node index %u points outside of valid range\n", node_index);
  ------------------
  |  |  246|     32|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 32]
  |  |  ------------------
  ------------------
  865|     32|        bplist->err = PLIST_ERR_PARSE;
  866|     32|        return NULL;
  867|     32|    }
  868|       |
  869|       |    /* check nesting depth */
  870|   218k|    if (bplist->level > PLIST_MAX_NESTING_DEPTH) {
  ------------------
  |  |   56|   218k|#define PLIST_MAX_NESTING_DEPTH NODE_MAX_DEPTH
  |  |  ------------------
  |  |  |  |   33|   218k|#define NODE_MAX_DEPTH 512
  |  |  ------------------
  ------------------
  |  Branch (870:9): [True: 0, False: 218k]
  ------------------
  871|      0|        PLIST_BIN_ERR("maximum nesting depth (%u) exceeded\n",(unsigned)PLIST_MAX_NESTING_DEPTH);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  872|      0|        bplist->err = PLIST_ERR_MAX_NESTING;
  873|      0|        return NULL;
  874|      0|    }
  875|       |
  876|       |    /* store node_index for current recursion level */
  877|   218k|    if ((uint32_t)ptr_array_size(bplist->used_indexes) < bplist->level+1) {
  ------------------
  |  Branch (877:9): [True: 3.94k, False: 214k]
  ------------------
  878|  7.89k|        while ((uint32_t)ptr_array_size(bplist->used_indexes) < bplist->level+1) {
  ------------------
  |  Branch (878:16): [True: 3.94k, False: 3.94k]
  ------------------
  879|  3.94k|            ptr_array_add(bplist->used_indexes, (void*)(uintptr_t)node_index);
  880|  3.94k|        }
  881|   214k|    } else {
  882|   214k|	ptr_array_set(bplist->used_indexes, (void*)(uintptr_t)node_index, bplist->level);
  883|   214k|    }
  884|       |
  885|       |    /* recursion check */
  886|   218k|    if (bplist->level > 0) {
  ------------------
  |  Branch (886:9): [True: 217k, False: 1.74k]
  ------------------
  887|  1.77M|        for (i = bplist->level-1; i >= 0; i--) {
  ------------------
  |  Branch (887:35): [True: 1.55M, False: 216k]
  ------------------
  888|  1.55M|            void *node_i = ptr_array_index(bplist->used_indexes, i);
  889|  1.55M|            void *node_level = ptr_array_index(bplist->used_indexes, bplist->level);
  890|  1.55M|            if (node_i == node_level) {
  ------------------
  |  Branch (890:17): [True: 284, False: 1.55M]
  ------------------
  891|    284|                PLIST_BIN_ERR("recursion detected in binary plist\n");
  ------------------
  |  |  246|    284|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 284]
  |  |  ------------------
  ------------------
  892|    284|                bplist->err = PLIST_ERR_CIRCULAR_REF;
  893|    284|                return NULL;
  894|    284|            }
  895|  1.55M|        }
  896|   217k|    }
  897|       |
  898|       |    /* finally parse node */
  899|   218k|    bplist->level++;
  900|   218k|    plist = parse_bin_node(bplist, &ptr);
  901|   218k|    bplist->level--;
  902|   218k|    return plist;
  903|   218k|}
bplist.c:parse_bin_node:
  662|   218k|{
  663|   218k|    uint16_t type = 0;
  664|   218k|    uint64_t size = 0;
  665|   218k|    uint64_t pobject = 0;
  666|   218k|    uint64_t poffset_table = (uint64_t)(uintptr_t)bplist->offset_table;
  667|       |
  668|   218k|    if (!object)
  ------------------
  |  Branch (668:9): [True: 0, False: 218k]
  ------------------
  669|      0|        return NULL;
  670|       |
  671|   218k|    type = (**object) & BPLIST_MASK;
  672|   218k|    size = (**object) & BPLIST_FILL;
  673|   218k|    (*object)++;
  674|       |
  675|   218k|    if (size == BPLIST_FILL) {
  ------------------
  |  Branch (675:9): [True: 8.06k, False: 210k]
  ------------------
  676|  8.06k|        switch (type) {
  677|    524|        case BPLIST_DATA:
  ------------------
  |  Branch (677:9): [True: 524, False: 7.54k]
  ------------------
  678|  1.11k|        case BPLIST_STRING:
  ------------------
  |  Branch (678:9): [True: 586, False: 7.48k]
  ------------------
  679|  2.57k|        case BPLIST_UNICODE:
  ------------------
  |  Branch (679:9): [True: 1.46k, False: 6.60k]
  ------------------
  680|  6.16k|        case BPLIST_ARRAY:
  ------------------
  |  Branch (680:9): [True: 3.59k, False: 4.46k]
  ------------------
  681|  6.55k|        case BPLIST_SET:
  ------------------
  |  Branch (681:9): [True: 382, False: 7.68k]
  ------------------
  682|  7.52k|        case BPLIST_DICT:
  ------------------
  |  Branch (682:9): [True: 973, False: 7.09k]
  ------------------
  683|  7.52k|        {
  684|  7.52k|            uint16_t next_size = **object & BPLIST_FILL;
  685|  7.52k|            if ((**object & BPLIST_MASK) != BPLIST_INT) {
  ------------------
  |  Branch (685:17): [True: 8, False: 7.51k]
  ------------------
  686|      8|                PLIST_BIN_ERR("%s: invalid size node type for node type 0x%02x: found 0x%02x, expected 0x%02x\n", __func__, type, **object & BPLIST_MASK, BPLIST_INT);
  ------------------
  |  |  246|      8|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 8]
  |  |  ------------------
  ------------------
  687|      8|                return NULL;
  688|      8|            }
  689|  7.51k|            (*object)++;
  690|  7.51k|            next_size = 1 << next_size;
  691|  7.51k|            if (*object + next_size > bplist->offset_table) {
  ------------------
  |  Branch (691:17): [True: 2, False: 7.51k]
  ------------------
  692|      2|                PLIST_BIN_ERR("%s: size node data bytes for node type 0x%02x point outside of valid range\n", __func__, type);
  ------------------
  |  |  246|      2|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 2]
  |  |  ------------------
  ------------------
  693|      2|                return NULL;
  694|      2|            }
  695|  7.51k|            size = UINT_TO_HOST(*object, next_size);
  ------------------
  |  |  187|  7.51k|	({ \
  |  |  188|  7.51k|		union plist_uint_ptr __up; \
  |  |  189|  7.51k|		__up.src = ((n) > 8) ? (const char*)(x) + ((n) - 8) : (const char*)(x); \
  |  |  ------------------
  |  |  |  Branch (189:14): [True: 3.62k, False: 3.88k]
  |  |  ------------------
  |  |  190|  7.51k|		((n) >= 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (190:4): [True: 5.11k, False: 2.39k]
  |  |  ------------------
  |  |  191|  7.51k|		((n) == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (191:4): [True: 318, False: 2.08k]
  |  |  ------------------
  |  |  192|  2.39k|		((n) == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (192:4): [True: 302, False: 1.77k]
  |  |  ------------------
  |  |  193|  2.08k|		((n) == 1 ? *__up.u8ptr : \
  |  |  ------------------
  |  |  |  Branch (193:4): [True: 1.77k, False: 0]
  |  |  ------------------
  |  |  194|  1.77k|		beNtoh( get_unaligned(__up.u64ptr), n) \
  |  |  ------------------
  |  |  |  |  170|  1.77k|#define beNtoh(x,n) be64toh((x) << ((8-(n)) << 3))
  |  |  ------------------
  |  |  195|  1.77k|		)))); \
  |  |  196|  7.51k|	})
  ------------------
  696|  7.51k|            (*object) += next_size;
  697|  7.51k|            break;
  698|  7.51k|        }
  699|    543|        default:
  ------------------
  |  Branch (699:9): [True: 543, False: 7.52k]
  ------------------
  700|    543|            break;
  701|  8.06k|        }
  702|  8.06k|    }
  703|       |
  704|   218k|    pobject = (uint64_t)(uintptr_t)*object;
  705|       |
  706|   218k|    switch (type)
  707|   218k|    {
  708|       |
  709|   100k|    case BPLIST_NULL:
  ------------------
  |  Branch (709:5): [True: 100k, False: 118k]
  ------------------
  710|   100k|        switch (size)
  711|   100k|        {
  712|       |
  713|    521|        case BPLIST_TRUE:
  ------------------
  |  Branch (713:9): [True: 521, False: 99.6k]
  ------------------
  714|    521|        {
  715|    521|            plist_data_t data = plist_new_plist_data();
  716|    521|            if (!data) {
  ------------------
  |  Branch (716:17): [True: 0, False: 521]
  ------------------
  717|      0|                PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  718|      0|                return NULL;
  719|      0|            }
  720|    521|            data->type = PLIST_BOOLEAN;
  721|    521|            data->boolval = TRUE;
  ------------------
  |  |   28|    521|#define TRUE 1
  ------------------
  722|    521|            data->length = 1;
  723|    521|            return node_create(NULL, data);
  724|    521|        }
  725|       |
  726|    365|        case BPLIST_FALSE:
  ------------------
  |  Branch (726:9): [True: 365, False: 99.7k]
  ------------------
  727|    365|        {
  728|    365|            plist_data_t data = plist_new_plist_data();
  729|    365|            if (!data) {
  ------------------
  |  Branch (729:17): [True: 0, False: 365]
  ------------------
  730|      0|                PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  731|      0|                return NULL;
  732|      0|            }
  733|    365|            data->type = PLIST_BOOLEAN;
  734|    365|            data->boolval = FALSE;
  ------------------
  |  |   32|    365|#define FALSE 0
  ------------------
  735|    365|            data->length = 1;
  736|    365|            return node_create(NULL, data);
  737|    365|        }
  738|       |
  739|  99.2k|        case BPLIST_NULL:
  ------------------
  |  Branch (739:9): [True: 99.2k, False: 888]
  ------------------
  740|  99.2k|        {
  741|  99.2k|            plist_data_t data = plist_new_plist_data();
  742|  99.2k|            if (!data) {
  ------------------
  |  Branch (742:17): [True: 0, False: 99.2k]
  ------------------
  743|      0|                PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  744|      0|                return NULL;
  745|      0|            }
  746|  99.2k|            data->type = PLIST_NULL;
  747|  99.2k|            data->length = 0;
  748|  99.2k|            return node_create(NULL, data);
  749|  99.2k|        }
  750|       |
  751|      2|        default:
  ------------------
  |  Branch (751:9): [True: 2, False: 100k]
  ------------------
  752|      2|            return NULL;
  753|   100k|        }
  754|       |
  755|  3.89k|    case BPLIST_INT:
  ------------------
  |  Branch (755:5): [True: 3.89k, False: 214k]
  ------------------
  756|  3.89k|        if (pobject + (uint64_t)(1 << size) > poffset_table) {
  ------------------
  |  Branch (756:13): [True: 27, False: 3.86k]
  ------------------
  757|     27|            PLIST_BIN_ERR("%s: BPLIST_INT data bytes point outside of valid range\n", __func__);
  ------------------
  |  |  246|     27|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 27]
  |  |  ------------------
  ------------------
  758|     27|            return NULL;
  759|     27|        }
  760|  3.86k|        return parse_int_node(object, size);
  761|       |
  762|    570|    case BPLIST_REAL:
  ------------------
  |  Branch (762:5): [True: 570, False: 217k]
  ------------------
  763|    570|        if (pobject + (uint64_t)(1 << size) > poffset_table) {
  ------------------
  |  Branch (763:13): [True: 27, False: 543]
  ------------------
  764|     27|            PLIST_BIN_ERR("%s: BPLIST_REAL data bytes point outside of valid range\n", __func__);
  ------------------
  |  |  246|     27|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 27]
  |  |  ------------------
  ------------------
  765|     27|            return NULL;
  766|     27|        }
  767|    543|        return parse_real_node(object, size);
  768|       |
  769|    261|    case BPLIST_DATE:
  ------------------
  |  Branch (769:5): [True: 261, False: 218k]
  ------------------
  770|    261|        if (3 != size) {
  ------------------
  |  Branch (770:13): [True: 5, False: 256]
  ------------------
  771|      5|            PLIST_BIN_ERR("%s: invalid data size for BPLIST_DATE node\n", __func__);
  ------------------
  |  |  246|      5|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 5]
  |  |  ------------------
  ------------------
  772|      5|            return NULL;
  773|      5|        }
  774|    256|        if (pobject + (uint64_t)(1 << size) > poffset_table) {
  ------------------
  |  Branch (774:13): [True: 6, False: 250]
  ------------------
  775|      6|            PLIST_BIN_ERR("%s: BPLIST_DATE data bytes point outside of valid range\n", __func__);
  ------------------
  |  |  246|      6|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 6]
  |  |  ------------------
  ------------------
  776|      6|            return NULL;
  777|      6|        }
  778|    250|        return parse_date_node(object, size);
  779|       |
  780|  33.7k|    case BPLIST_DATA:
  ------------------
  |  Branch (780:5): [True: 33.7k, False: 184k]
  ------------------
  781|  33.7k|        if (pobject + size < pobject || pobject + size > poffset_table) {
  ------------------
  |  Branch (781:13): [True: 2, False: 33.7k]
  |  Branch (781:41): [True: 105, False: 33.5k]
  ------------------
  782|    107|            PLIST_BIN_ERR("%s: BPLIST_DATA data bytes point outside of valid range\n", __func__);
  ------------------
  |  |  246|    107|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 107]
  |  |  ------------------
  ------------------
  783|    107|            return NULL;
  784|    107|        }
  785|  33.5k|        return parse_data_node(object, size);
  786|       |
  787|  42.2k|    case BPLIST_STRING:
  ------------------
  |  Branch (787:5): [True: 42.2k, False: 176k]
  ------------------
  788|  42.2k|        if (pobject + size < pobject || pobject + size > poffset_table) {
  ------------------
  |  Branch (788:13): [True: 0, False: 42.2k]
  |  Branch (788:41): [True: 101, False: 42.1k]
  ------------------
  789|    101|            PLIST_BIN_ERR("%s: BPLIST_STRING data bytes point outside of valid range\n", __func__);
  ------------------
  |  |  246|    101|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 101]
  |  |  ------------------
  ------------------
  790|    101|            return NULL;
  791|    101|        }
  792|  42.1k|        return parse_string_node(object, size);
  793|       |
  794|  6.73k|    case BPLIST_UNICODE:
  ------------------
  |  Branch (794:5): [True: 6.73k, False: 211k]
  ------------------
  795|  6.73k|        if (size*2 < size) {
  ------------------
  |  Branch (795:13): [True: 71, False: 6.66k]
  ------------------
  796|     71|            PLIST_BIN_ERR("%s: Integer overflow when calculating BPLIST_UNICODE data size.\n", __func__);
  ------------------
  |  |  246|     71|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 71]
  |  |  ------------------
  ------------------
  797|     71|            return NULL;
  798|     71|        }
  799|  6.66k|        if (pobject + size*2 < pobject || pobject + size*2 > poffset_table) {
  ------------------
  |  Branch (799:13): [True: 1, False: 6.66k]
  |  Branch (799:43): [True: 127, False: 6.53k]
  ------------------
  800|    128|            PLIST_BIN_ERR("%s: BPLIST_UNICODE data bytes point outside of valid range\n", __func__);
  ------------------
  |  |  246|    128|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 128]
  |  |  ------------------
  ------------------
  801|    128|            return NULL;
  802|    128|        }
  803|  6.53k|        return parse_unicode_node(object, size);
  804|       |
  805|  3.53k|    case BPLIST_SET:
  ------------------
  |  Branch (805:5): [True: 3.53k, False: 214k]
  ------------------
  806|  20.6k|    case BPLIST_ARRAY:
  ------------------
  |  Branch (806:5): [True: 17.0k, False: 201k]
  ------------------
  807|  20.6k|        if (pobject + size < pobject || pobject + size > poffset_table) {
  ------------------
  |  Branch (807:13): [True: 1, False: 20.6k]
  |  Branch (807:41): [True: 99, False: 20.5k]
  ------------------
  808|    100|            PLIST_BIN_ERR("%s: BPLIST_ARRAY data bytes point outside of valid range\n", __func__);
  ------------------
  |  |  246|    100|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 100]
  |  |  ------------------
  ------------------
  809|    100|            return NULL;
  810|    100|        }
  811|  20.5k|        return parse_array_node(bplist, object, size);
  812|       |
  813|  5.87k|    case BPLIST_UID:
  ------------------
  |  Branch (813:5): [True: 5.87k, False: 212k]
  ------------------
  814|  5.87k|        if (pobject + size+1 > poffset_table) {
  ------------------
  |  Branch (814:13): [True: 7, False: 5.86k]
  ------------------
  815|      7|            PLIST_BIN_ERR("%s: BPLIST_UID data bytes point outside of valid range\n", __func__);
  ------------------
  |  |  246|      7|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 7]
  |  |  ------------------
  ------------------
  816|      7|            return NULL;
  817|      7|        }
  818|  5.86k|        return parse_uid_node(object, size);
  819|       |
  820|  4.42k|    case BPLIST_DICT:
  ------------------
  |  Branch (820:5): [True: 4.42k, False: 214k]
  ------------------
  821|  4.42k|        if (pobject + size < pobject || pobject + size > poffset_table) {
  ------------------
  |  Branch (821:13): [True: 2, False: 4.42k]
  |  Branch (821:41): [True: 102, False: 4.32k]
  ------------------
  822|    104|            PLIST_BIN_ERR("%s: BPLIST_DICT data bytes point outside of valid range\n", __func__);
  ------------------
  |  |  246|    104|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 104]
  |  |  ------------------
  ------------------
  823|    104|            return NULL;
  824|    104|        }
  825|  4.32k|        return parse_dict_node(bplist, object, size);
  826|       |
  827|      3|    default:
  ------------------
  |  Branch (827:5): [True: 3, False: 218k]
  ------------------
  828|      3|        PLIST_BIN_ERR("%s: unexpected node type 0x%02x\n", __func__, type);
  ------------------
  |  |  246|      3|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 3]
  |  |  ------------------
  ------------------
  829|      3|        return NULL;
  830|   218k|    }
  831|      0|    return NULL;
  832|   218k|}
bplist.c:parse_int_node:
  279|  3.86k|{
  280|  3.86k|    plist_data_t data = plist_new_plist_data();
  281|  3.86k|    if (!data) {
  ------------------
  |  Branch (281:9): [True: 0, False: 3.86k]
  ------------------
  282|      0|        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  283|      0|        return NULL;
  284|      0|    }
  285|       |
  286|  3.86k|    size = 1 << size;			// make length less misleading
  287|  3.86k|    switch (size)
  288|  3.86k|    {
  289|    225|    case sizeof(uint8_t):
  ------------------
  |  Branch (289:5): [True: 225, False: 3.64k]
  ------------------
  290|  1.34k|    case sizeof(uint16_t):
  ------------------
  |  Branch (290:5): [True: 1.12k, False: 2.74k]
  ------------------
  291|  2.38k|    case sizeof(uint32_t):
  ------------------
  |  Branch (291:5): [True: 1.03k, False: 2.83k]
  ------------------
  292|  3.34k|    case sizeof(uint64_t):
  ------------------
  |  Branch (292:5): [True: 965, False: 2.90k]
  ------------------
  293|  3.34k|        data->length = sizeof(uint64_t);
  294|  3.34k|        break;
  295|    516|    case 16:
  ------------------
  |  Branch (295:5): [True: 516, False: 3.34k]
  ------------------
  296|    516|        data->length = size;
  297|    516|        break;
  298|      2|    default:
  ------------------
  |  Branch (298:5): [True: 2, False: 3.86k]
  ------------------
  299|      2|        free(data);
  300|      2|        PLIST_BIN_ERR("%s: Invalid byte size for integer node\n", __func__);
  ------------------
  |  |  246|      2|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 2]
  |  |  ------------------
  ------------------
  301|      2|        return NULL;
  302|  3.86k|    };
  303|       |
  304|  3.86k|    data->intval = UINT_TO_HOST(*bnode, size);
  ------------------
  |  |  187|  3.86k|	({ \
  |  |  188|  3.86k|		union plist_uint_ptr __up; \
  |  |  189|  3.86k|		__up.src = ((n) > 8) ? (const char*)(x) + ((n) - 8) : (const char*)(x); \
  |  |  ------------------
  |  |  |  Branch (189:14): [True: 516, False: 3.34k]
  |  |  ------------------
  |  |  190|  3.86k|		((n) >= 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (190:4): [True: 1.48k, False: 2.38k]
  |  |  ------------------
  |  |  191|  3.86k|		((n) == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (191:4): [True: 1.03k, False: 1.34k]
  |  |  ------------------
  |  |  192|  2.38k|		((n) == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (192:4): [True: 1.12k, False: 225]
  |  |  ------------------
  |  |  193|  1.34k|		((n) == 1 ? *__up.u8ptr : \
  |  |  ------------------
  |  |  |  Branch (193:4): [True: 225, False: 0]
  |  |  ------------------
  |  |  194|    225|		beNtoh( get_unaligned(__up.u64ptr), n) \
  |  |  ------------------
  |  |  |  |  170|    225|#define beNtoh(x,n) be64toh((x) << ((8-(n)) << 3))
  |  |  ------------------
  |  |  195|    225|		)))); \
  |  |  196|  3.86k|	})
  ------------------
  305|       |
  306|  3.86k|    (*bnode) += size;
  307|  3.86k|    data->type = PLIST_INT;
  308|       |
  309|       |    return node_create(NULL, data);
  310|  3.86k|}
bplist.c:parse_real_node:
  313|    793|{
  314|    793|    plist_data_t data = plist_new_plist_data();
  315|    793|    if (!data) {
  ------------------
  |  Branch (315:9): [True: 0, False: 793]
  ------------------
  316|      0|        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  317|      0|        return NULL;
  318|      0|    }
  319|       |
  320|    793|    size = 1 << size;			// make length less misleading
  321|    793|    switch (size)
  322|    793|    {
  323|    200|    case sizeof(uint32_t):
  ------------------
  |  Branch (323:5): [True: 200, False: 593]
  ------------------
  324|    200|    {
  325|    200|        uint32_t ival;
  326|    200|        memcpy(&ival, *bnode, sizeof(uint32_t));
  327|    200|        ival = float_bswap32(ival);
  ------------------
  |  |  213|    200|#define float_bswap32(x) bswap32(x)
  |  |  ------------------
  |  |  |  |  126|    200|#define bswap32(x)   ((((x) & 0xFF000000) >> 24) \
  |  |  |  |  127|    200|                    | (((x) & 0x00FF0000) >>  8) \
  |  |  |  |  128|    200|                    | (((x) & 0x0000FF00) <<  8) \
  |  |  |  |  129|    200|                    | (((x) & 0x000000FF) << 24))
  |  |  ------------------
  ------------------
  328|    200|        float fval;
  329|    200|        memcpy(&fval, &ival, sizeof(float));
  330|    200|        data->realval = fval;
  331|    200|    }
  332|    200|    break;
  333|       |
  334|    590|    case sizeof(uint64_t):
  ------------------
  |  Branch (334:5): [True: 590, False: 203]
  ------------------
  335|    590|    {
  336|    590|        uint64_t ival;
  337|    590|        memcpy(&ival, *bnode, sizeof(uint64_t));
  338|    590|        ival = float_bswap64(ival);
  ------------------
  |  |  212|    590|#define float_bswap64(x) bswap64(x)
  |  |  ------------------
  |  |  |  |  133|    590|#define bswap64(x)   ((((x) & 0xFF00000000000000ull) >> 56) \
  |  |  |  |  134|    590|                    | (((x) & 0x00FF000000000000ull) >> 40) \
  |  |  |  |  135|    590|                    | (((x) & 0x0000FF0000000000ull) >> 24) \
  |  |  |  |  136|    590|                    | (((x) & 0x000000FF00000000ull) >>  8) \
  |  |  |  |  137|    590|                    | (((x) & 0x00000000FF000000ull) <<  8) \
  |  |  |  |  138|    590|                    | (((x) & 0x0000000000FF0000ull) << 24) \
  |  |  |  |  139|    590|                    | (((x) & 0x000000000000FF00ull) << 40) \
  |  |  |  |  140|    590|                    | (((x) & 0x00000000000000FFull) << 56))
  |  |  ------------------
  ------------------
  339|    590|        memcpy(&data->realval, &ival, sizeof(double));
  340|    590|        break;
  341|      0|    }
  342|       |
  343|      3|    default:
  ------------------
  |  Branch (343:5): [True: 3, False: 790]
  ------------------
  344|      3|        free(data);
  345|      3|        PLIST_BIN_ERR("%s: Invalid byte size for real node\n", __func__);
  ------------------
  |  |  246|      3|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 3]
  |  |  ------------------
  ------------------
  346|      3|        return NULL;
  347|    793|    }
  348|    790|    data->type = PLIST_REAL;
  349|    790|    data->length = sizeof(double);
  350|       |
  351|       |    return node_create(NULL, data);
  352|    793|}
bplist.c:parse_date_node:
  355|    250|{
  356|    250|    plist_t node = parse_real_node(bnode, size);
  357|    250|    plist_data_t data = plist_get_data(node);
  358|       |
  359|    250|    data->type = PLIST_DATE;
  360|       |
  361|    250|    return node;
  362|    250|}
bplist.c:parse_data_node:
  479|  33.5k|{
  480|  33.5k|    plist_data_t data = plist_new_plist_data();
  481|  33.5k|    if (!data) {
  ------------------
  |  Branch (481:9): [True: 0, False: 33.5k]
  ------------------
  482|      0|        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  483|      0|        return NULL;
  484|      0|    }
  485|  33.5k|    data->type = PLIST_DATA;
  486|  33.5k|    data->length = size;
  487|  33.5k|    data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size);
  488|  33.5k|    if (!data->buff) {
  ------------------
  |  Branch (488:9): [True: 0, False: 33.5k]
  ------------------
  489|      0|        plist_free_data(data);
  490|      0|        PLIST_BIN_ERR("%s: Could not allocate %" PRIu64 " bytes\n", __func__, sizeof(uint8_t) * size);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  491|      0|        return NULL;
  492|      0|    }
  493|  33.5k|    memcpy(data->buff, *bnode, sizeof(uint8_t) * size);
  494|       |
  495|       |    return node_create(NULL, data);
  496|  33.5k|}
bplist.c:parse_string_node:
  365|  42.1k|{
  366|  42.1k|    plist_data_t data = plist_new_plist_data();
  367|  42.1k|    if (!data) {
  ------------------
  |  Branch (367:9): [True: 0, False: 42.1k]
  ------------------
  368|      0|        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  369|      0|        return NULL;
  370|      0|    }
  371|       |
  372|  42.1k|    data->type = PLIST_STRING;
  373|  42.1k|    data->strval = (char *) malloc(sizeof(char) * (size + 1));
  374|  42.1k|    if (!data->strval) {
  ------------------
  |  Branch (374:9): [True: 0, False: 42.1k]
  ------------------
  375|      0|        plist_free_data(data);
  376|      0|        PLIST_BIN_ERR("%s: Could not allocate %" PRIu64 " bytes\n", __func__, sizeof(char) * (size + 1));
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  377|      0|        return NULL;
  378|      0|    }
  379|  42.1k|    memcpy(data->strval, *bnode, size);
  380|  42.1k|    data->strval[size] = '\0';
  381|  42.1k|    data->length = strlen(data->strval);
  382|       |
  383|       |    return node_create(NULL, data);
  384|  42.1k|}
bplist.c:parse_unicode_node:
  458|  6.53k|{
  459|  6.53k|    plist_data_t data = plist_new_plist_data();
  460|  6.53k|    if (!data) {
  ------------------
  |  Branch (460:9): [True: 0, False: 6.53k]
  ------------------
  461|      0|        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  462|      0|        return NULL;
  463|      0|    }
  464|  6.53k|    size_t items_read = 0;
  465|  6.53k|    size_t items_written = 0;
  466|       |
  467|  6.53k|    data->type = PLIST_STRING;
  468|  6.53k|    data->strval = plist_utf16be_to_utf8((uint16_t*)(*bnode), size, &items_read, &items_written);
  469|  6.53k|    if (!data->strval) {
  ------------------
  |  Branch (469:9): [True: 2, False: 6.53k]
  ------------------
  470|      2|        plist_free_data(data);
  471|      2|        return NULL;
  472|      2|    }
  473|  6.53k|    data->length = items_written;
  474|       |
  475|       |    return node_create(NULL, data);
  476|  6.53k|}
bplist.c:plist_utf16be_to_utf8:
  387|  6.53k|{
  388|  6.53k|	if (!unistr || (len <= 0)) return NULL;
  ------------------
  |  Branch (388:6): [True: 0, False: 6.53k]
  |  Branch (388:17): [True: 2, False: 6.53k]
  ------------------
  389|  6.53k|	char* outbuf;
  390|  6.53k|	char* outbuf_new;
  391|  6.53k|	size_t p = 0;
  392|  6.53k|	size_t i = 0;
  393|       |
  394|  6.53k|	uint16_t wc;
  395|  6.53k|	uint32_t w;
  396|  6.53k|	int read_lead_surrogate = 0;
  397|       |
  398|       |	/* allocate with enough space */
  399|  6.53k|	outbuf = (char*)malloc(4*(len+1));
  400|  6.53k|	if (!outbuf) {
  ------------------
  |  Branch (400:6): [True: 0, False: 6.53k]
  ------------------
  401|      0|		PLIST_BIN_ERR("%s: Could not allocate %" PRIu64 " bytes\n", __func__, (uint64_t)(4*(len+1)));
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  402|      0|		return NULL;
  403|      0|	}
  404|       |
  405|   313k|	while (i < len) {
  ------------------
  |  Branch (405:9): [True: 307k, False: 6.53k]
  ------------------
  406|   307k|		wc = UINT_TO_HOST(unistr + i, sizeof(wc));
  ------------------
  |  |  187|   307k|	({ \
  |  |  188|   307k|		union plist_uint_ptr __up; \
  |  |  189|   307k|		__up.src = ((n) > 8) ? (const char*)(x) + ((n) - 8) : (const char*)(x); \
  |  |  ------------------
  |  |  |  Branch (189:14): [Folded, False: 307k]
  |  |  ------------------
  |  |  190|   307k|		((n) >= 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (190:4): [Folded, False: 307k]
  |  |  ------------------
  |  |  191|   307k|		((n) == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (191:4): [Folded, False: 307k]
  |  |  ------------------
  |  |  192|   307k|		((n) == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (192:4): [True: 307k, Folded]
  |  |  ------------------
  |  |  193|   307k|		((n) == 1 ? *__up.u8ptr : \
  |  |  ------------------
  |  |  |  Branch (193:4): [Folded, False: 0]
  |  |  ------------------
  |  |  194|      0|		beNtoh( get_unaligned(__up.u64ptr), n) \
  |  |  ------------------
  |  |  |  |  170|      0|#define beNtoh(x,n) be64toh((x) << ((8-(n)) << 3))
  |  |  ------------------
  |  |  195|      0|		)))); \
  |  |  196|   307k|	})
  ------------------
  407|   307k|		i++;
  408|   307k|		if (wc >= 0xD800 && wc <= 0xDBFF) {
  ------------------
  |  Branch (408:7): [True: 16.0k, False: 291k]
  |  Branch (408:23): [True: 2.30k, False: 13.7k]
  ------------------
  409|  2.30k|			if (!read_lead_surrogate) {
  ------------------
  |  Branch (409:8): [True: 1.78k, False: 525]
  ------------------
  410|  1.78k|				read_lead_surrogate = 1;
  411|  1.78k|				w = 0x010000 + ((wc & 0x3FF) << 10);
  412|  1.78k|			} else {
  413|       |				// This is invalid, the next 16 bit char should be a trail surrogate.
  414|       |				// Handling error by skipping.
  415|    525|				read_lead_surrogate = 0;
  416|    525|			}
  417|   304k|		} else if (wc >= 0xDC00 && wc <= 0xDFFF) {
  ------------------
  |  Branch (417:14): [True: 13.7k, False: 291k]
  |  Branch (417:30): [True: 1.20k, False: 12.5k]
  ------------------
  418|  1.20k|			if (read_lead_surrogate) {
  ------------------
  |  Branch (418:8): [True: 286, False: 922]
  ------------------
  419|    286|				read_lead_surrogate = 0;
  420|    286|				w = w | (wc & 0x3FF);
  421|    286|				outbuf[p++] = (char)(0xF0 + ((w >> 18) & 0x7));
  422|    286|				outbuf[p++] = (char)(0x80 + ((w >> 12) & 0x3F));
  423|    286|				outbuf[p++] = (char)(0x80 + ((w >> 6) & 0x3F));
  424|    286|				outbuf[p++] = (char)(0x80 + (w & 0x3F));
  425|    922|			} else {
  426|       |				// This is invalid.  A trail surrogate should always follow a lead surrogate.
  427|       |				// Handling error by skipping
  428|    922|			}
  429|   303k|		} else if (wc >= 0x800) {
  ------------------
  |  Branch (429:14): [True: 192k, False: 110k]
  ------------------
  430|   192k|			outbuf[p++] = (char)(0xE0 + ((wc >> 12) & 0xF));
  431|   192k|			outbuf[p++] = (char)(0x80 + ((wc >> 6) & 0x3F));
  432|   192k|			outbuf[p++] = (char)(0x80 + (wc & 0x3F));
  433|   192k|		} else if (wc >= 0x80) {
  ------------------
  |  Branch (433:14): [True: 21.9k, False: 88.9k]
  ------------------
  434|  21.9k|			outbuf[p++] = (char)(0xC0 + ((wc >> 6) & 0x1F));
  435|  21.9k|			outbuf[p++] = (char)(0x80 + (wc & 0x3F));
  436|  88.9k|		} else {
  437|  88.9k|			outbuf[p++] = (char)(wc & 0x7F);
  438|  88.9k|		}
  439|   307k|	}
  440|  6.53k|	if (items_read) {
  ------------------
  |  Branch (440:6): [True: 6.53k, False: 0]
  ------------------
  441|  6.53k|		*items_read = i;
  442|  6.53k|	}
  443|  6.53k|	if (items_written) {
  ------------------
  |  Branch (443:6): [True: 6.53k, False: 0]
  ------------------
  444|  6.53k|		*items_written = p;
  445|  6.53k|	}
  446|  6.53k|	outbuf[p] = 0;
  447|       |
  448|       |	/* reduce the size to the actual size */
  449|  6.53k|	outbuf_new = (char*)realloc(outbuf, p+1);
  450|  6.53k|	if (outbuf_new) {
  ------------------
  |  Branch (450:6): [True: 6.53k, False: 0]
  ------------------
  451|  6.53k|		outbuf = outbuf_new;
  452|  6.53k|	}
  453|       |
  454|  6.53k|	return outbuf;
  455|  6.53k|}
bplist.c:parse_array_node:
  587|  20.5k|{
  588|  20.5k|    uint64_t j;
  589|  20.5k|    uint64_t str_j = 0;
  590|  20.5k|    uint64_t index1;
  591|  20.5k|    plist_data_t data = plist_new_plist_data();
  592|  20.5k|    if (!data) {
  ------------------
  |  Branch (592:9): [True: 0, False: 20.5k]
  ------------------
  593|      0|        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  594|      0|        return NULL;
  595|      0|    }
  596|  20.5k|    const char *index1_ptr = NULL;
  597|       |
  598|  20.5k|    data->type = PLIST_ARRAY;
  599|  20.5k|    data->length = size;
  600|       |
  601|  20.5k|    plist_t node = node_create(NULL, data);
  602|  20.5k|    if (!node) {
  ------------------
  |  Branch (602:9): [True: 0, False: 20.5k]
  ------------------
  603|      0|        plist_free_data(data);
  604|      0|        PLIST_BIN_ERR("%s: failed to create node\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  605|      0|        return NULL;
  606|      0|    }
  607|       |
  608|   195k|    for (j = 0; j < data->length; j++) {
  ------------------
  |  Branch (608:17): [True: 176k, False: 19.3k]
  ------------------
  609|   176k|        str_j = j * bplist->ref_size;
  610|   176k|        index1_ptr = (*bnode) + str_j;
  611|       |
  612|   176k|        if (index1_ptr < bplist->data || index1_ptr + bplist->ref_size > bplist->offset_table) {
  ------------------
  |  Branch (612:13): [True: 0, False: 176k]
  |  Branch (612:42): [True: 5, False: 176k]
  ------------------
  613|      5|            plist_free(node);
  614|      5|            PLIST_BIN_ERR("%s: array item %" PRIu64 " is outside of valid range\n", __func__, j);
  ------------------
  |  |  246|      5|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 5]
  |  |  ------------------
  ------------------
  615|      5|            return NULL;
  616|      5|        }
  617|       |
  618|   176k|        index1 = UINT_TO_HOST(index1_ptr, bplist->ref_size);
  ------------------
  |  |  187|   176k|	({ \
  |  |  188|   176k|		union plist_uint_ptr __up; \
  |  |  189|   176k|		__up.src = ((n) > 8) ? (const char*)(x) + ((n) - 8) : (const char*)(x); \
  |  |  ------------------
  |  |  |  Branch (189:14): [True: 242, False: 176k]
  |  |  ------------------
  |  |  190|   176k|		((n) >= 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (190:4): [True: 264, False: 176k]
  |  |  ------------------
  |  |  191|   176k|		((n) == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (191:4): [True: 269, False: 175k]
  |  |  ------------------
  |  |  192|   176k|		((n) == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (192:4): [True: 288, False: 175k]
  |  |  ------------------
  |  |  193|   175k|		((n) == 1 ? *__up.u8ptr : \
  |  |  ------------------
  |  |  |  Branch (193:4): [True: 175k, False: 298]
  |  |  ------------------
  |  |  194|   175k|		beNtoh( get_unaligned(__up.u64ptr), n) \
  |  |  ------------------
  |  |  |  |  170|   175k|#define beNtoh(x,n) be64toh((x) << ((8-(n)) << 3))
  |  |  ------------------
  |  |  195|   175k|		)))); \
  |  |  196|   176k|	})
  ------------------
  619|       |
  620|   176k|        if (index1 >= bplist->num_objects) {
  ------------------
  |  Branch (620:13): [True: 210, False: 176k]
  ------------------
  621|    210|            plist_free(node);
  622|    210|            PLIST_BIN_ERR("%s: array item %" PRIu64 " object index (%" PRIu64 ") must be smaller than the number of objects (%" PRIu64 ")\n", __func__, j, index1, bplist->num_objects);
  ------------------
  |  |  246|    210|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 210]
  |  |  ------------------
  ------------------
  623|    210|            return NULL;
  624|    210|        }
  625|       |
  626|       |        /* process value node */
  627|   176k|        plist_t val = parse_bin_node_at_index(bplist, index1);
  628|   176k|        if (!val) {
  ------------------
  |  Branch (628:13): [True: 985, False: 175k]
  ------------------
  629|    985|            plist_free(node);
  630|    985|            return NULL;
  631|    985|        }
  632|       |
  633|   175k|        node_attach((node_t)node, (node_t)val);
  634|   175k|    }
  635|       |
  636|  19.3k|    return node;
  637|  20.5k|}
bplist.c:parse_uid_node:
  640|  5.86k|{
  641|  5.86k|    plist_data_t data = plist_new_plist_data();
  642|  5.86k|    if (!data) {
  ------------------
  |  Branch (642:9): [True: 0, False: 5.86k]
  ------------------
  643|      0|        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  644|      0|        return NULL;
  645|      0|    }
  646|  5.86k|    size = size + 1;
  647|  5.86k|    data->intval = UINT_TO_HOST(*bnode, size);
  ------------------
  |  |  187|  5.86k|	({ \
  |  |  188|  5.86k|		union plist_uint_ptr __up; \
  |  |  189|  5.86k|		__up.src = ((n) > 8) ? (const char*)(x) + ((n) - 8) : (const char*)(x); \
  |  |  ------------------
  |  |  |  Branch (189:14): [True: 1.95k, False: 3.90k]
  |  |  ------------------
  |  |  190|  5.86k|		((n) >= 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (190:4): [True: 2.00k, False: 3.86k]
  |  |  ------------------
  |  |  191|  5.86k|		((n) == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (191:4): [True: 1.63k, False: 2.22k]
  |  |  ------------------
  |  |  192|  3.86k|		((n) == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (192:4): [True: 1.39k, False: 836]
  |  |  ------------------
  |  |  193|  2.22k|		((n) == 1 ? *__up.u8ptr : \
  |  |  ------------------
  |  |  |  Branch (193:4): [True: 211, False: 625]
  |  |  ------------------
  |  |  194|    836|		beNtoh( get_unaligned(__up.u64ptr), n) \
  |  |  ------------------
  |  |  |  |  170|    836|#define beNtoh(x,n) be64toh((x) << ((8-(n)) << 3))
  |  |  ------------------
  |  |  195|    836|		)))); \
  |  |  196|  5.86k|	})
  ------------------
  648|  5.86k|    if (data->intval > UINT32_MAX) {
  ------------------
  |  Branch (648:9): [True: 63, False: 5.80k]
  ------------------
  649|     63|        PLIST_BIN_ERR("%s: value %" PRIu64 " too large for UID node (must be <= %u)\n", __func__, (uint64_t)data->intval, UINT32_MAX);
  ------------------
  |  |  246|     63|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 63]
  |  |  ------------------
  ------------------
  650|     63|        free(data);
  651|     63|        return NULL;
  652|     63|    }
  653|       |
  654|  5.80k|    (*bnode) += size;
  655|  5.80k|    data->type = PLIST_UID;
  656|  5.80k|    data->length = sizeof(uint64_t);
  657|       |
  658|       |    return node_create(NULL, data);
  659|  5.86k|}
bplist.c:parse_dict_node:
  499|  4.32k|{
  500|  4.32k|    uint64_t j;
  501|  4.32k|    uint64_t str_i = 0, str_j = 0;
  502|  4.32k|    uint64_t index1, index2;
  503|  4.32k|    plist_data_t data = plist_new_plist_data();
  504|  4.32k|    if (!data) {
  ------------------
  |  Branch (504:9): [True: 0, False: 4.32k]
  ------------------
  505|      0|        PLIST_BIN_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  506|      0|        return NULL;
  507|      0|    }
  508|  4.32k|    const char *index1_ptr = NULL;
  509|  4.32k|    const char *index2_ptr = NULL;
  510|       |
  511|  4.32k|    data->type = PLIST_DICT;
  512|  4.32k|    data->length = size;
  513|       |
  514|  4.32k|    plist_t node = node_create(NULL, data);
  515|  4.32k|    if (!node) {
  ------------------
  |  Branch (515:9): [True: 0, False: 4.32k]
  ------------------
  516|      0|        plist_free_data(data);
  517|      0|        PLIST_BIN_ERR("%s: failed to create node\n", __func__);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  518|      0|        return NULL;
  519|      0|    }
  520|       |
  521|  24.1k|    for (j = 0; j < data->length; j++) {
  ------------------
  |  Branch (521:17): [True: 20.8k, False: 3.27k]
  ------------------
  522|  20.8k|        str_i = j * bplist->ref_size;
  523|  20.8k|        str_j = (j + size) * bplist->ref_size;
  524|  20.8k|        index1_ptr = (*bnode) + str_i;
  525|  20.8k|        index2_ptr = (*bnode) + str_j;
  526|       |
  527|  20.8k|        if ((index1_ptr < bplist->data || index1_ptr + bplist->ref_size > bplist->offset_table) ||
  ------------------
  |  Branch (527:14): [True: 0, False: 20.8k]
  |  Branch (527:43): [True: 3, False: 20.8k]
  ------------------
  528|  20.8k|            (index2_ptr < bplist->data || index2_ptr + bplist->ref_size > bplist->offset_table)) {
  ------------------
  |  Branch (528:14): [True: 0, False: 20.8k]
  |  Branch (528:43): [True: 21, False: 20.8k]
  ------------------
  529|     24|            plist_free(node);
  530|     24|            PLIST_BIN_ERR("%s: dict entry %" PRIu64 " is outside of valid range\n", __func__, j);
  ------------------
  |  |  246|     24|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 24]
  |  |  ------------------
  ------------------
  531|     24|            return NULL;
  532|     24|        }
  533|       |
  534|  20.8k|        index1 = UINT_TO_HOST(index1_ptr, bplist->ref_size);
  ------------------
  |  |  187|  20.8k|	({ \
  |  |  188|  20.8k|		union plist_uint_ptr __up; \
  |  |  189|  20.8k|		__up.src = ((n) > 8) ? (const char*)(x) + ((n) - 8) : (const char*)(x); \
  |  |  ------------------
  |  |  |  Branch (189:14): [True: 208, False: 20.6k]
  |  |  ------------------
  |  |  190|  20.8k|		((n) >= 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (190:4): [True: 242, False: 20.6k]
  |  |  ------------------
  |  |  191|  20.8k|		((n) == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (191:4): [True: 226, False: 20.3k]
  |  |  ------------------
  |  |  192|  20.6k|		((n) == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (192:4): [True: 235, False: 20.1k]
  |  |  ------------------
  |  |  193|  20.3k|		((n) == 1 ? *__up.u8ptr : \
  |  |  ------------------
  |  |  |  Branch (193:4): [True: 19.8k, False: 313]
  |  |  ------------------
  |  |  194|  20.1k|		beNtoh( get_unaligned(__up.u64ptr), n) \
  |  |  ------------------
  |  |  |  |  170|  20.1k|#define beNtoh(x,n) be64toh((x) << ((8-(n)) << 3))
  |  |  ------------------
  |  |  195|  20.1k|		)))); \
  |  |  196|  20.8k|	})
  ------------------
  535|  20.8k|        index2 = UINT_TO_HOST(index2_ptr, bplist->ref_size);
  ------------------
  |  |  187|  20.8k|	({ \
  |  |  188|  20.8k|		union plist_uint_ptr __up; \
  |  |  189|  20.8k|		__up.src = ((n) > 8) ? (const char*)(x) + ((n) - 8) : (const char*)(x); \
  |  |  ------------------
  |  |  |  Branch (189:14): [True: 208, False: 20.6k]
  |  |  ------------------
  |  |  190|  20.8k|		((n) >= 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (190:4): [True: 242, False: 20.6k]
  |  |  ------------------
  |  |  191|  20.8k|		((n) == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (191:4): [True: 226, False: 20.3k]
  |  |  ------------------
  |  |  192|  20.6k|		((n) == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \
  |  |  ------------------
  |  |  |  Branch (192:4): [True: 235, False: 20.1k]
  |  |  ------------------
  |  |  193|  20.3k|		((n) == 1 ? *__up.u8ptr : \
  |  |  ------------------
  |  |  |  Branch (193:4): [True: 19.8k, False: 313]
  |  |  ------------------
  |  |  194|  20.1k|		beNtoh( get_unaligned(__up.u64ptr), n) \
  |  |  ------------------
  |  |  |  |  170|  20.1k|#define beNtoh(x,n) be64toh((x) << ((8-(n)) << 3))
  |  |  ------------------
  |  |  195|  20.1k|		)))); \
  |  |  196|  20.8k|	})
  ------------------
  536|       |
  537|  20.8k|        if (index1 >= bplist->num_objects) {
  ------------------
  |  Branch (537:13): [True: 122, False: 20.7k]
  ------------------
  538|    122|            plist_free(node);
  539|    122|            PLIST_BIN_ERR("%s: dict entry %" PRIu64 ": key index (%" PRIu64 ") must be smaller than the number of objects (%" PRIu64 ")\n", __func__, j, index1, bplist->num_objects);
  ------------------
  |  |  246|    122|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 122]
  |  |  ------------------
  ------------------
  540|    122|            return NULL;
  541|    122|        }
  542|  20.7k|        if (index2 >= bplist->num_objects) {
  ------------------
  |  Branch (542:13): [True: 117, False: 20.6k]
  ------------------
  543|    117|            plist_free(node);
  544|    117|            PLIST_BIN_ERR("%s: dict entry %" PRIu64 ": value index (%" PRIu64 ") must be smaller than the number of objects (%" PRIu64 ")\n", __func__, j, index1, bplist->num_objects);
  ------------------
  |  |  246|    117|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 117]
  |  |  ------------------
  ------------------
  545|    117|            return NULL;
  546|    117|        }
  547|       |
  548|       |        /* process key node */
  549|  20.6k|        plist_t key = parse_bin_node_at_index(bplist, index1);
  550|  20.6k|        if (!key) {
  ------------------
  |  Branch (550:13): [True: 499, False: 20.1k]
  ------------------
  551|    499|            plist_free(node);
  552|    499|            return NULL;
  553|    499|        }
  554|       |
  555|  20.1k|        if (plist_get_data(key)->type != PLIST_STRING) {
  ------------------
  |  Branch (555:13): [True: 3, False: 20.1k]
  ------------------
  556|      3|            PLIST_BIN_ERR("%s: dict entry %" PRIu64 ": invalid node type for key\n", __func__, j);
  ------------------
  |  |  246|      3|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 3]
  |  |  ------------------
  ------------------
  557|      3|            plist_free(key);
  558|      3|            plist_free(node);
  559|      3|            return NULL;
  560|      3|        }
  561|       |
  562|       |        /* enforce key type */
  563|  20.1k|        plist_get_data(key)->type = PLIST_KEY;
  564|  20.1k|        if (!plist_get_data(key)->strval) {
  ------------------
  |  Branch (564:13): [True: 0, False: 20.1k]
  ------------------
  565|      0|            PLIST_BIN_ERR("%s: dict entry %" PRIu64 ": key must not be NULL\n", __func__, j);
  ------------------
  |  |  246|      0|#define PLIST_BIN_ERR(...) if (plist_bin_debug) { fprintf(stderr, "libplist[binparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (246:32): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  566|      0|            plist_free(key);
  567|      0|            plist_free(node);
  568|      0|            return NULL;
  569|      0|        }
  570|       |
  571|       |        /* process value node */
  572|  20.1k|        plist_t val = parse_bin_node_at_index(bplist, index2);
  573|  20.1k|        if (!val) {
  ------------------
  |  Branch (573:13): [True: 283, False: 19.8k]
  ------------------
  574|    283|            plist_free(key);
  575|    283|            plist_free(node);
  576|    283|            return NULL;
  577|    283|        }
  578|       |
  579|  19.8k|        node_attach((node_t)node, (node_t)key);
  580|  19.8k|        node_attach((node_t)node, (node_t)val);
  581|  19.8k|    }
  582|       |
  583|  3.27k|    return node;
  584|  4.32k|}

hash_table_destroy:
   38|  4.32k|{
   39|  4.32k|	if (!ht) return;
  ------------------
  |  Branch (39:6): [True: 4.32k, False: 0]
  ------------------
   40|       |
   41|      0|	int i = 0;
   42|      0|	for (i = 0; i < 4096; i++) {
  ------------------
  |  Branch (42:14): [True: 0, False: 0]
  ------------------
   43|      0|		if (ht->entries[i]) {
  ------------------
  |  Branch (43:7): [True: 0, False: 0]
  ------------------
   44|      0|			hashentry_t* e = ht->entries[i];
   45|      0|			while (e) {
  ------------------
  |  Branch (45:11): [True: 0, False: 0]
  ------------------
   46|      0|				if (ht->free_func) {
  ------------------
  |  Branch (46:9): [True: 0, False: 0]
  ------------------
   47|      0|					ht->free_func(e->value);
   48|      0|				}
   49|      0|				hashentry_t* old = e;
   50|      0|				e = e->next;
   51|      0|				free(old);
   52|      0|			}
   53|      0|		}
   54|      0|	}
   55|      0|	free(ht);
   56|      0|}

plist_json_init:
   56|      2|{
   57|       |    /* init JSON stuff */
   58|      2|#ifdef DEBUG
   59|      2|    char *env_debug = getenv("PLIST_JSON_DEBUG");
   60|      2|    if (env_debug && !strcmp(env_debug, "1")) {
  ------------------
  |  Branch (60:9): [True: 0, False: 2]
  |  Branch (60:22): [True: 0, False: 0]
  ------------------
   61|      0|        plist_json_debug = 1;
   62|      0|    }
   63|      2|#endif
   64|      2|}

plist_ostep_init:
   54|      2|{
   55|       |    /* init OpenStep stuff */
   56|      2|#ifdef DEBUG
   57|      2|    char *env_debug = getenv("PLIST_OSTEP_DEBUG");
   58|      2|    if (env_debug && !strcmp(env_debug, "1")) {
  ------------------
  |  Branch (58:9): [True: 0, False: 2]
  |  Branch (58:22): [True: 0, False: 0]
  ------------------
   59|      0|        plist_ostep_debug = 1;
   60|      0|    }
   61|      2|#endif
   62|      2|}

plist.c:internal_plist_init:
  153|      2|{
  154|      2|    plist_bin_init();
  155|      2|    plist_xml_init();
  156|      2|    plist_json_init();
  157|      2|    plist_ostep_init();
  158|      2|    atexit(internal_plist_deinit);
  159|      2|}
plist_get_data:
  353|   278k|{
  354|   278k|    if (!node)
  ------------------
  |  Branch (354:9): [True: 0, False: 278k]
  ------------------
  355|      0|        return NULL;
  356|   278k|    return (plist_data_t)((node_t)node)->data;
  357|   278k|}
plist_new_plist_data:
  360|   217k|{
  361|   217k|    return (plist_data_t) calloc(1, sizeof(struct plist_data_s));
  362|   217k|}
plist_free_data:
  421|   217k|{
  422|   217k|    if (!data) return;
  ------------------
  |  Branch (422:9): [True: 0, False: 217k]
  ------------------
  423|   217k|    _plist_free_data(data);
  424|   217k|    free(data);
  425|   217k|}
plist_free:
  713|  4.92k|{
  714|  4.92k|    if (plist)
  ------------------
  |  Branch (714:9): [True: 2.73k, False: 2.19k]
  ------------------
  715|  2.73k|    {
  716|  2.73k|        plist_free_node((node_t)plist);
  717|  2.73k|    }
  718|  4.92k|}
plist.c:_plist_free_data:
  390|   217k|{
  391|   217k|    if (!data) return;
  ------------------
  |  Branch (391:9): [True: 0, False: 217k]
  ------------------
  392|   217k|    switch (data->type) {
  393|  20.1k|        case PLIST_KEY:
  ------------------
  |  Branch (393:9): [True: 20.1k, False: 197k]
  ------------------
  394|  48.6k|        case PLIST_STRING:
  ------------------
  |  Branch (394:9): [True: 28.5k, False: 189k]
  ------------------
  395|  48.6k|            free(data->strval);
  396|  48.6k|            data->strval = NULL;
  397|  48.6k|            break;
  398|  33.5k|        case PLIST_DATA:
  ------------------
  |  Branch (398:9): [True: 33.5k, False: 184k]
  ------------------
  399|  33.5k|            free(data->buff);
  400|  33.5k|            data->buff = NULL;
  401|  33.5k|            break;
  402|  20.5k|        case PLIST_ARRAY:
  ------------------
  |  Branch (402:9): [True: 20.5k, False: 197k]
  ------------------
  403|  20.5k|            ptr_array_free((ptrarray_t*)data->hashtable);
  404|  20.5k|            data->hashtable = NULL;
  405|  20.5k|            break;
  406|  4.32k|        case PLIST_DICT: {
  ------------------
  |  Branch (406:9): [True: 4.32k, False: 213k]
  ------------------
  407|  4.32k|            hashtable_t *ht = (hashtable_t*)data->hashtable;
  408|       |            // PLIST_DICT hashtables must not own/free values; values are freed via node tree.
  409|  4.32k|            assert(!ht || ht->free_func == NULL);
  ------------------
  |  Branch (409:13): [True: 4.32k, False: 0]
  |  Branch (409:13): [True: 0, False: 0]
  |  Branch (409:13): [True: 4.32k, False: 0]
  |  Branch (409:13): [True: 0, False: 0]
  ------------------
  410|  4.32k|            if (ht) ht->free_func = NULL;
  ------------------
  |  Branch (410:17): [True: 0, False: 4.32k]
  ------------------
  411|  4.32k|            hash_table_destroy(ht);
  412|  4.32k|            data->hashtable = NULL;
  413|  4.32k|            break;
  414|  4.32k|        }
  415|   110k|        default:
  ------------------
  |  Branch (415:9): [True: 110k, False: 107k]
  ------------------
  416|   110k|            break;
  417|   217k|    }
  418|   217k|}
plist.c:plist_free_node:
  500|  2.73k|{
  501|  2.73k|    if (!root) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (501:9): [True: 0, False: 2.73k]
  ------------------
  502|       |
  503|  2.73k|    int root_index = -1;
  504|       |
  505|  2.73k|    if (root->parent) {
  ------------------
  |  Branch (505:9): [True: 0, False: 2.73k]
  ------------------
  506|      0|        root_index = node_detach(root->parent, root);
  507|      0|        if (root_index < 0) {
  ------------------
  |  Branch (507:13): [True: 0, False: 0]
  ------------------
  508|      0|            return root_index;
  509|      0|        }
  510|      0|    }
  511|       |
  512|  2.73k|    int r = plist_free_children(root);
  513|  2.73k|    if (r < 0) {
  ------------------
  |  Branch (513:9): [True: 0, False: 2.73k]
  ------------------
  514|       |        // root is already detached; caller should treat as error.
  515|      0|        return r;
  516|      0|    }
  517|       |
  518|  2.73k|    plist_data_t data = plist_get_data(root);
  519|  2.73k|    plist_free_data(data);
  520|  2.73k|    root->data = NULL;
  521|       |
  522|  2.73k|    node_destroy(root);
  523|       |
  524|  2.73k|    return root_index;
  525|  2.73k|}
plist.c:plist_free_children:
  428|  2.73k|{
  429|  2.73k|    if (!root) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (429:9): [True: 0, False: 2.73k]
  ------------------
  430|       |
  431|  2.73k|    if (!node_first_child(root)) {
  ------------------
  |  Branch (431:9): [True: 2.01k, False: 721]
  ------------------
  432|  2.01k|        return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|  2.01k|#define NODE_ERR_SUCCESS       0
  ------------------
  433|  2.01k|    }
  434|       |
  435|    721|    size_t cap = 64, sp = 0;
  436|    721|    node_t *stack = (node_t*)malloc(cap * sizeof(*stack));
  437|    721|    if (!stack) return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  |  Branch (437:9): [True: 0, False: 721]
  ------------------
  438|       |
  439|       |    // Push *direct* children onto the stack, detached from root.
  440|  10.4k|    for (;;) {
  441|  10.4k|        node_t ch = node_first_child(root);
  442|  10.4k|        if (!ch) break;
  ------------------
  |  Branch (442:13): [True: 721, False: 9.72k]
  ------------------
  443|       |
  444|  9.72k|        int di = node_detach(root, ch);
  445|  9.72k|        if (di < 0) {
  ------------------
  |  Branch (445:13): [True: 0, False: 9.72k]
  ------------------
  446|      0|            free(stack);
  447|      0|            return di;
  448|      0|        }
  449|       |
  450|  9.72k|        if (sp == cap) {
  ------------------
  |  Branch (450:13): [True: 87, False: 9.63k]
  ------------------
  451|     87|            cap += 64;
  452|     87|            node_t *tmp = (node_t*)realloc(stack, cap * sizeof(*stack));
  453|     87|            if (!tmp) {
  ------------------
  |  Branch (453:17): [True: 0, False: 87]
  ------------------
  454|      0|                free(stack);
  455|      0|                return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  456|      0|            }
  457|     87|            stack = tmp;
  458|     87|        }
  459|  9.72k|        stack[sp++] = ch;
  460|  9.72k|    }
  461|       |
  462|       |    // Now free the detached subtree nodes (and their descendants).
  463|   420k|    while (sp) {
  ------------------
  |  Branch (463:12): [True: 420k, False: 721]
  ------------------
  464|   420k|        node_t node = stack[sp - 1];
  465|   420k|        node_t ch = node_first_child(node);
  466|   420k|        if (ch) {
  ------------------
  |  Branch (466:13): [True: 205k, False: 214k]
  ------------------
  467|   205k|            int di = node_detach(node, ch);
  468|   205k|            if (di < 0) {
  ------------------
  |  Branch (468:17): [True: 0, False: 205k]
  ------------------
  469|      0|                free(stack);
  470|      0|                return di;
  471|      0|            }
  472|       |
  473|   205k|            if (sp == cap) {
  ------------------
  |  Branch (473:17): [True: 6, False: 205k]
  ------------------
  474|      6|                cap += 64;
  475|      6|                node_t *tmp = (node_t*)realloc(stack, cap * sizeof(*stack));
  476|      6|                if (!tmp) {
  ------------------
  |  Branch (476:21): [True: 0, False: 6]
  ------------------
  477|      0|                    free(stack);
  478|      0|                    return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  479|      0|                }
  480|      6|                stack = tmp;
  481|      6|            }
  482|   205k|            stack[sp++] = ch;
  483|   205k|            continue;
  484|   205k|        }
  485|       |
  486|   214k|        plist_data_t data = plist_get_data(node);
  487|   214k|        plist_free_data(data);
  488|   214k|        node->data = NULL;
  489|       |
  490|   214k|        node_destroy(node);
  491|       |
  492|   214k|        sp--;
  493|   214k|    }
  494|       |
  495|    721|    free(stack);
  496|    721|    return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|    721|#define NODE_ERR_SUCCESS       0
  ------------------
  497|    721|}

ptr_array_new:
   25|  1.89k|{
   26|  1.89k|	ptrarray_t *pa = (ptrarray_t*)malloc(sizeof(ptrarray_t));
   27|  1.89k|	pa->pdata = (void**)malloc(sizeof(void*) * capacity);
   28|  1.89k|	pa->capacity = capacity;
   29|  1.89k|	pa->capacity_step = (capacity > 4096) ? 4096 : capacity;
  ------------------
  |  Branch (29:22): [True: 0, False: 1.89k]
  ------------------
   30|  1.89k|	pa->len = 0;
   31|  1.89k|	return pa;
   32|  1.89k|}
ptr_array_free:
   35|  22.4k|{
   36|  22.4k|	if (!pa) return;
  ------------------
  |  Branch (36:6): [True: 20.5k, False: 1.89k]
  ------------------
   37|  1.89k|	if (pa->pdata) {
  ------------------
  |  Branch (37:6): [True: 1.89k, False: 0]
  ------------------
   38|  1.89k|		free(pa->pdata);
   39|  1.89k|	}
   40|  1.89k|	free(pa);
   41|  1.89k|}
ptr_array_insert:
   44|  3.94k|{
   45|  3.94k|	if (!pa || !pa->pdata) return;
  ------------------
  |  Branch (45:6): [True: 0, False: 3.94k]
  |  Branch (45:13): [True: 0, False: 3.94k]
  ------------------
   46|  3.94k|	long remaining = pa->capacity-pa->len;
   47|  3.94k|	if (remaining == 0) {
  ------------------
  |  Branch (47:6): [True: 55, False: 3.89k]
  ------------------
   48|     55|		pa->pdata = (void**)realloc(pa->pdata, sizeof(void*) * (pa->capacity + pa->capacity_step));
   49|     55|		pa->capacity += pa->capacity_step;
   50|     55|	}
   51|  3.94k|	if (array_index < 0 || array_index >= pa->len) {
  ------------------
  |  Branch (51:6): [True: 3.94k, False: 0]
  |  Branch (51:25): [True: 0, False: 0]
  ------------------
   52|  3.94k|		pa->pdata[pa->len] = data;
   53|  3.94k|	} else {
   54|      0|		memmove(&pa->pdata[array_index+1], &pa->pdata[array_index], (pa->len-array_index) * sizeof(void*));
   55|      0|		pa->pdata[array_index] = data;
   56|      0|	}
   57|  3.94k|	pa->len++;
   58|  3.94k|}
ptr_array_add:
   61|  3.94k|{
   62|  3.94k|	ptr_array_insert(pa, data, -1);
   63|  3.94k|}
ptr_array_set:
   78|   214k|{
   79|   214k|	if (!pa || !pa->pdata || array_index < 0) return;
  ------------------
  |  Branch (79:6): [True: 0, False: 214k]
  |  Branch (79:13): [True: 0, False: 214k]
  |  Branch (79:27): [True: 0, False: 214k]
  ------------------
   80|   214k|	if (pa->len == 0 || array_index >= pa->len) return;
  ------------------
  |  Branch (80:6): [True: 0, False: 214k]
  |  Branch (80:22): [True: 0, False: 214k]
  ------------------
   81|   214k|	pa->pdata[array_index] = data;
   82|   214k|}
ptr_array_index:
   85|  3.11M|{
   86|  3.11M|	if (!pa) return NULL;
  ------------------
  |  Branch (86:6): [True: 0, False: 3.11M]
  ------------------
   87|  3.11M|	if (array_index < 0 || array_index >= pa->len) {
  ------------------
  |  Branch (87:6): [True: 0, False: 3.11M]
  |  Branch (87:25): [True: 0, False: 3.11M]
  ------------------
   88|      0|		return NULL;
   89|      0|	}
   90|  3.11M|	return pa->pdata[array_index];
   91|  3.11M|}
ptr_array_size:
   94|   226k|{
   95|   226k|	return pa->len;
   96|   226k|}

plist_xml_init:
   91|      2|{
   92|       |    /* init XML stuff */
   93|      2|#ifdef DEBUG
   94|      2|    char *env_debug = getenv("PLIST_XML_DEBUG");
   95|      2|    if (env_debug && !strcmp(env_debug, "1")) {
  ------------------
  |  Branch (95:9): [True: 0, False: 2]
  |  Branch (95:22): [True: 0, False: 0]
  ------------------
   96|      0|        plist_xml_debug = 1;
   97|      0|    }
   98|      2|#endif
   99|      2|}

