int KSI_FTLV_memReadN(const unsigned char *buf, size_t buf_len, KSI_FTLV *arr, size_t arr_len, size_t *rd) { int res = KSI_UNKNOWN_ERROR; const unsigned char *ptr = buf; size_t len = buf_len; size_t i = 0; /* Dummy buffer, used if arr == NULL. */ KSI_FTLV dummy; size_t off = 0; if (buf == NULL || buf_len == 0 || (arr != NULL && arr_len == 0) || (arr == NULL && arr_len != 0)) { res = KSI_INVALID_ARGUMENT; goto cleanup; } /* Read up-to arr_len tlvs from the buffer. */ while ((arr_len == 0 || i < arr_len) && len > 0) { size_t tlvLen; KSI_FTLV *target = (arr == NULL ? &dummy : &arr[i]); /* Read the next tlv. */ res = KSI_FTLV_memRead(ptr, len, target); if (res != KSI_OK) goto cleanup; target->off = off; /* Calculate consumed bytes. */ tlvLen = target->hdr_len + target->dat_len; ptr += tlvLen; len -= tlvLen; off += tlvLen; ++i; } /* If the output variable is set, evaluate it. */ if (rd != NULL) { *rd = i; } res = KSI_OK; cleanup: return res; }
static int generateNextTlv(struct generator_st *gen, KSI_TLV **tlv) { int res = KSI_UNKNOWN_ERROR; unsigned char *buf = NULL; size_t consumed = 0; KSI_FTLV ftlv; if (gen == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } if (gen->tlv != NULL) { KSI_TLV_free(gen->tlv); gen->tlv = NULL; } /* Try to parse only when there is something left to parse. */ if (gen->len > 0) { memset(&ftlv, 0, sizeof(ftlv)); res = KSI_FTLV_memRead(gen->ptr, gen->len, &ftlv); if (res != KSI_OK) { KSI_pushError(gen->ctx, res, NULL); goto cleanup; } consumed = ftlv.hdr_len + ftlv.dat_len; buf = KSI_malloc(consumed); if (buf == NULL) { KSI_pushError(gen->ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } memcpy(buf, gen->ptr, consumed); gen->ptr += consumed; gen->len -= consumed; /* Make sure the buffer is not overflowing. */ if (consumed > UINT_MAX){ KSI_pushError(gen->ctx, res = KSI_INVALID_FORMAT, "Input too large."); goto cleanup; } if (consumed > 0) { if (gen->hasSignature) { /* The signature must be the last element. */ KSI_pushError(gen->ctx, res = KSI_INVALID_FORMAT, "The signature must be the last element."); goto cleanup; } res = KSI_TLV_parseBlob2(gen->ctx, buf, (unsigned)consumed, 1, &gen->tlv); if (res != KSI_OK) { KSI_pushError(gen->ctx, res, NULL); goto cleanup; } buf = NULL; if (KSI_TLV_getTag(gen->tlv) == 0x0704) { gen->sig_offset = gen->offset; gen->hasSignature = true; } } } gen->offset += consumed; *tlv = gen->tlv; res = KSI_OK; cleanup: KSI_free(buf); return res; }