index_build (p11_index *index,
             CK_OBJECT_HANDLE handle,
             CK_ATTRIBUTE **attrs,
             CK_ATTRIBUTE *merge)
{
	CK_ATTRIBUTE *extra = NULL;
	CK_ATTRIBUTE *built;
	p11_array *stack = NULL;
	CK_ULONG count;
	CK_ULONG nattrs;
	CK_ULONG nmerge;
	CK_ULONG nextra;
	CK_RV rv;
	int i;

	rv = index->build (index->data, index, *attrs, merge, &extra);
	if (rv != CKR_OK)
		return rv;

	/* Short circuit when nothing to merge */
	if (*attrs == NULL && extra == NULL) {
		built = merge;
		stack = NULL;

	} else {
		stack = p11_array_new (NULL);
		nattrs = p11_attrs_count (*attrs);
		nmerge = p11_attrs_count (merge);
		nextra = p11_attrs_count (extra);

		/* Make a shallow copy of the combined attributes for validation */
		built = calloc (nmerge + nattrs + nextra + 1, sizeof (CK_ATTRIBUTE));
		return_val_if_fail (built != NULL, CKR_GENERAL_ERROR);

		count = nmerge;
		memcpy (built, merge, sizeof (CK_ATTRIBUTE) * nmerge);
		p11_array_push (stack, merge);
		merge_attrs (built, &count, *attrs, nattrs, stack);
		merge_attrs (built, &count, extra, nextra, stack);

		/* The terminator attribute */
		built[count].type = CKA_INVALID;
		assert (p11_attrs_terminator (built + count));
	}

	rv = index->store (index->data, index, handle, &built);

	if (rv == CKR_OK) {
		for (i = 0; stack && i < stack->num; i++)
			free (stack->elem[i]);
		*attrs = built;
	} else {
		p11_attrs_free (extra);
		free (built);
	}

	p11_array_free (stack);
	return rv;
}
index_build (p11_index *index,
             CK_OBJECT_HANDLE handle,
             CK_ATTRIBUTE **attrs,
             CK_ATTRIBUTE *merge)
{
	CK_ATTRIBUTE *extra = NULL;
	CK_ATTRIBUTE *built;
	p11_array *stack = NULL;
	CK_ULONG count;
	CK_ULONG nattrs;
	CK_ULONG nmerge;
	CK_ULONG nextra;
	CK_RV rv;
	int i;

	rv = index->build (index->data, index, *attrs, merge, &extra);
	if (rv != CKR_OK)
		return rv;

	 
	if (*attrs == NULL && extra == NULL) {
		built = merge;
		stack = NULL;

	} else {
		stack = p11_array_new (NULL);
		nattrs = p11_attrs_count (*attrs);
		nmerge = p11_attrs_count (merge);
		nextra = p11_attrs_count (extra);

		 
		built = calloc (nmerge + nattrs + nextra + 1, sizeof (CK_ATTRIBUTE));
		return_val_if_fail (built != NULL, CKR_GENERAL_ERROR);

		count = nmerge;
		memcpy (built, merge, sizeof (CK_ATTRIBUTE) * nmerge);
		p11_array_push (stack, merge);
		merge_attrs (built, &count, *attrs, nattrs, stack);
		merge_attrs (built, &count, extra, nextra, stack);

		 
		built[count].type = CKA_INVALID;
		assert (p11_attrs_terminator (built + count));
	}

	rv = index->store (index->data, index, handle, &built);

	if (rv == CKR_OK) {
		for (i = 0; stack && i < stack->num; i++)
			free (stack->elem[i]);
		*attrs = built;
	} else {
		p11_attrs_free (extra);
		free (built);
	}

	p11_array_free (stack);
	return rv;
}