From d328cbbdc256197d02ec03eef0022b4122d38bb8 Mon Sep 17 00:00:00 2001 From: David Timber Date: Sun, 19 Jan 2020 13:12:29 +1100 Subject: bin pack redesign. resolv bug fix --- src/pack.c | 430 ++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 254 insertions(+), 176 deletions(-) (limited to 'src/pack.c') diff --git a/src/pack.c b/src/pack.c index 59816eb..96ca4d8 100644 --- a/src/pack.c +++ b/src/pack.c @@ -5,224 +5,302 @@ #include #include #include +#include #include -#include -#include #include #include -#include +#include + + +struct prne_unpack_ctx { + size_t end; + z_stream zs; +}; + +static int bin_tpl_comp_func (const void *a, const void *b) { + return ((const prne_bin_tuple_t*)a)->arch < ((const prne_bin_tuple_t*)b)->arch ? -1 : ((const prne_bin_tuple_t*)a)->arch > ((const prne_bin_tuple_t*)b)->arch ? 1 : 0; +} void prne_init_bin_archive (prne_bin_archive_t *a) { a->data_size = 0; a->data = NULL; - a->nb_binaries = 0; - a->arch_arr = NULL; - a->offset_arr = NULL; - a->size_arr = NULL; + a->nb_bin = 0; + a->bin = NULL; } -void prne_init_unpack_bin_archive_result (prne_unpack_bin_archive_result_t *r) { - r->data_size = 0; - r->data = NULL; - r->result = PRNE_UNPACK_BIN_ARCHIVE_OK; - r->err = 0; +void prne_free_bin_archive (prne_bin_archive_t *a) { + prne_free(a->data); + prne_free(a->bin); + a->data_size = 0; + a->data = NULL; + a->nb_bin = 0; + a->bin = NULL; } -prne_unpack_bin_archive_result_t prne_unpack_bin_archive (const int fd) { - static const size_t fd_buf_size = 77, b64_buf_size = 58, z_buf_size = 1024; - - prne_unpack_bin_archive_result_t ret; - uint8_t *mem = NULL, *fd_buf = NULL, *b64_buf = NULL, *z_buf = NULL; - int fd_read_size, fd_data_size, rem_size = 0; - int z_func_ret; - z_stream stream; - size_t dec_b64_size, z_out_size; - void *ny_buf; - bool stream_end; - - prne_init_unpack_bin_archive_result(&ret); - memzero(&stream, sizeof(z_stream)); - - mem = (uint8_t*)prne_malloc(1, fd_buf_size + b64_buf_size + z_buf_size); - if (mem == NULL) { - ret.result = PRNE_UNPACK_BIN_ARCHIVE_MEM_ERR; +prne_pack_ret_t prne_index_bin_archive (void *rf_ctx, prne_bin_archive_read_ft rf, prne_bin_archive_t *out) { + prne_pack_ret_t ret; + uint8_t *data = NULL; + prne_bin_tuple_t *bin = NULL; + size_t i, r_len, pos = 0, data_size = 0, nb_bin = 0; + uint8_t head[4]; + void *ny_mem; + const size_t pagesize = prne_getpagesize(); + + r_len = 0; + ret = rf(rf_ctx, 1, head, &r_len); + if (ret.rc != PRNE_PACK_RC_OK) { + goto ERR; + } + if (r_len != 1) { + ret.rc = PRNE_PACK_RC_FMT_ERR; + goto ERR; + } + + nb_bin = head[0]; + bin = (prne_bin_tuple_t*)prne_malloc(sizeof(prne_bin_tuple_t), nb_bin); + if (bin == NULL) { + ret.rc = PRNE_PACK_RC_ERRNO; ret.err = errno; - goto END; + goto ERR; } - fd_buf = mem; - b64_buf = mem + fd_buf_size; - z_buf = mem + fd_buf_size + b64_buf_size; + for (i = 0; i < nb_bin; i += 1) { + r_len = 0; + ret = rf(rf_ctx, 4, head, &r_len); + if (ret.rc != PRNE_PACK_RC_OK) { + goto ERR; + } + if (r_len != 4) { + ret.rc = PRNE_PACK_RC_FMT_ERR; + goto ERR; + } - z_func_ret = inflateInit(&stream); - if (z_func_ret != Z_OK) { - ret.result = PRNE_UNPACK_BIN_ARCHIVE_Z_ERR; - ret.err = z_func_ret; - goto END; + bin[i].arch = (prne_arch_t)head[0]; + bin[i].offset = pos; + pos += bin[i].size = ((size_t)head[1] << 16) | ((size_t)head[2] << 8) | ((size_t)head[3]); } - stream_end = false; + pos = 0; do { - fd_read_size = read(fd, fd_buf + rem_size, fd_buf_size - rem_size); - if (fd_read_size < 0) { - ret.result = PRNE_UNPACK_BIN_ARCHIVE_ERRNO; + ny_mem = prne_realloc(data, 1, pos + pagesize); + if (ny_mem == NULL) { + ret.rc = PRNE_PACK_RC_ERRNO; ret.err = errno; - goto END; - } - if (fd_read_size == 0) { - break; + goto ERR; } - fd_read_size += rem_size; - - fd_read_size = fd_data_size = prne_str_shift_spaces((char*)fd_buf, (size_t)fd_read_size); - fd_data_size = fd_data_size / 4 * 4; - rem_size = fd_read_size - fd_data_size; - - if (fd_data_size > 0) { - ret.err = mbedtls_base64_decode(b64_buf, b64_buf_size, &dec_b64_size, fd_buf, fd_data_size); - if (ret.err != 0) { - ret.result = PRNE_UNPACK_BIN_ARCHIVE_CRYPTO_ERR; - } - - if (dec_b64_size > 0) { - stream.avail_in = dec_b64_size; - stream.next_in = b64_buf; - do { - stream.avail_out = z_buf_size; - stream.next_out = z_buf; - z_func_ret = inflate(&stream, Z_NO_FLUSH); - switch (z_func_ret) { - case Z_STREAM_END: - stream_end = true; - break; - case Z_OK: - case Z_BUF_ERROR: - break; - default: - ret.result = PRNE_UNPACK_BIN_ARCHIVE_Z_ERR; - ret.err = z_func_ret; - goto END; - } - - z_out_size = z_buf_size - stream.avail_out; - if (z_out_size > 0) { - ny_buf = prne_realloc(ret.data, 1, ret.data_size + z_out_size); - if (ny_buf == NULL) { - ret.result = PRNE_UNPACK_BIN_ARCHIVE_MEM_ERR; - ret.err = errno; - break; - } - ret.data = (uint8_t*)ny_buf; - - memcpy(ret.data + ret.data_size, z_buf, z_out_size); - ret.data_size += z_out_size; - } - } while (stream.avail_out == 0); - } + data = (uint8_t*)ny_mem; + + ret = rf(rf_ctx, pagesize, data + pos, &r_len); + if (ret.rc != PRNE_PACK_RC_OK) { + goto ERR; } + data_size += r_len; + pos += pagesize; + } while (r_len == pagesize); + ny_mem = prne_realloc(data, 1, data_size); + if (ny_mem == NULL) { + ret.rc = PRNE_PACK_RC_ERRNO; + ret.err = errno; + goto ERR; + } + data = (uint8_t*)ny_mem; + + qsort(bin, nb_bin, sizeof(prne_bin_tuple_t), bin_tpl_comp_func); + out->data = data; + out->data_size = data_size; + out->nb_bin = nb_bin; + out->bin = bin; + + return ret; +ERR: + prne_free(bin); + prne_free(data); + + return ret; +} - memmove(fd_buf, fd_buf + fd_data_size, rem_size); - } while (!stream_end); +prne_unpack_ctx_pt prne_alloc_unpack_ctx (const prne_bin_archive_t *archive, const prne_arch_t arch, prne_pack_ret_t *pr_out) { + prne_bin_tuple_t main_tpl; + prne_bin_tuple_t *tpl; + prne_unpack_ctx_pt ret = NULL; + uint8_t buf[4096]; + size_t i, cnt; + prne_pack_ret_t pr; - if (ret.data_size == 0) { - ret.result = PRNE_UNPACK_BIN_ARCHIVE_FMT_ERR; + pr.rc = PRNE_PACK_RC_OK; + pr.err = 0; + + main_tpl.arch = arch; + tpl = (prne_bin_tuple_t*)bsearch(&main_tpl, archive->bin, archive->nb_bin, sizeof(prne_bin_tuple_t), bin_tpl_comp_func); + if (tpl == NULL) { + pr.rc = PRNE_PACK_RC_NO_BIN; + goto ERR; } + main_tpl = *tpl; -END: - prne_free(mem); - if (ret.result != PRNE_UNPACK_BIN_ARCHIVE_OK) { - prne_free(ret.data); - ret.data = NULL; - ret.data_size = 0; + ret = (prne_unpack_ctx_pt)prne_malloc(sizeof(struct prne_unpack_ctx), 1); + if (ret == NULL) { + pr.rc = PRNE_PACK_RC_ERRNO; + pr.err = errno; + goto ERR; + } + memzero(&ret->zs, sizeof(ret->zs)); + if (Z_OK != (pr.err = inflateInit(&ret->zs))) { + prne_free(ret); + ret = NULL; + + pr.rc = PRNE_PACK_RC_Z_ERR; + goto ERR; } - inflateEnd(&stream); + ret->zs.avail_in = archive->data_size; + ret->zs.next_in = archive->data; + cnt = main_tpl.offset / sizeof(buf); + for (i = 0; i < cnt; i += 1) { + ret->zs.avail_out = sizeof(buf); + ret->zs.next_out = buf; + switch (inflate(&ret->zs, Z_SYNC_FLUSH)) { + case Z_OK: + case Z_BUF_ERROR: + break; + default: + pr.rc = PRNE_PACK_RC_FMT_ERR; + goto ERR; + } + if (ret->zs.avail_out != 0) { + pr.rc = PRNE_PACK_RC_FMT_ERR; + goto ERR; + } + } + + ret->zs.avail_out = main_tpl.offset - cnt * sizeof(buf); + ret->zs.next_out = buf; + switch (inflate(&ret->zs, Z_SYNC_FLUSH)) { + case Z_OK: + case Z_BUF_ERROR: + break; + default: + pr.rc = PRNE_PACK_RC_FMT_ERR; + goto ERR; + } + if (ret->zs.total_out != main_tpl.offset) { + pr.rc = PRNE_PACK_RC_FMT_ERR; + goto ERR; + } + + ret->end = main_tpl.offset + main_tpl.size; + if (pr_out != NULL) { + *pr_out = pr; + } return ret; +ERR: + if (ret != NULL) { + inflateEnd(&ret->zs); + prne_free(ret); + } + if (pr_out != NULL) { + *pr_out = pr; + } + + return NULL; } -prne_index_bin_archive_result_code_t prne_index_bin_archive (prne_unpack_bin_archive_result_t *in, prne_bin_archive_t *out) { - prne_index_bin_archive_result_code_t ret = PRNE_INDEX_BIN_ARCHIVE_OK; - size_t buf_pos = 0, arr_cnt = 0, offset_arr[NB_PRNE_ARCH], size_arr[NB_PRNE_ARCH]; - prne_arch_t arch; - uint_fast32_t bin_size; - prne_arch_t arch_arr[NB_PRNE_ARCH]; - prne_bin_archive_t archive; - - memzero(arch_arr, sizeof(prne_arch_t) * NB_PRNE_ARCH); - memzero(offset_arr, sizeof(size_t) * NB_PRNE_ARCH); - memzero(size_arr, sizeof(size_t) * NB_PRNE_ARCH); - prne_init_bin_archive(&archive); +void prne_free_unpack_ctx (prne_unpack_ctx_pt ctx) { + if (ctx != NULL) { + inflateEnd(&ctx->zs); + prne_free(ctx); + } +} - do { - if (buf_pos + 4 >= in->data_size || arr_cnt >= NB_PRNE_ARCH) { - ret = PRNE_INDEX_BIN_ARCHIVE_FMT_ERR; - goto END; - } +ssize_t prne_do_unpack (prne_unpack_ctx_pt ctx, uint8_t *out, const size_t out_len, prne_pack_ret_t *pr_out) { + const size_t rem = ctx->end - ctx->zs.total_out; + const size_t req = prne_op_min(rem, out_len); + prne_pack_ret_t pr; - arch = (prne_arch_t)in->data[buf_pos]; - bin_size = - ((uint_fast32_t)in->data[buf_pos + 1] << 16) | - ((uint_fast32_t)in->data[buf_pos + 2] << 8) | - (uint_fast32_t)in->data[buf_pos + 3]; - if (prne_arch_tostr(arch) == NULL || bin_size == 0 || buf_pos + 4 + bin_size > in->data_size) { - ret = PRNE_INDEX_BIN_ARCHIVE_FMT_ERR; - goto END; - } + pr.rc = PRNE_PACK_RC_OK; + pr.err = 0; - arch_arr[arr_cnt] = arch; - offset_arr[arr_cnt] = 4 + buf_pos; - size_arr[arr_cnt] = bin_size; - arr_cnt += 1; - - buf_pos += 4 + bin_size; - } while (buf_pos < in->data_size); - - archive.arch_arr = (prne_arch_t*)prne_malloc(sizeof(prne_arch_t), arr_cnt); - archive.offset_arr = (size_t*)prne_malloc(sizeof(size_t), arr_cnt); - archive.size_arr = (size_t*)prne_malloc(sizeof(size_t), arr_cnt); - if (archive.arch_arr == NULL || archive.offset_arr == NULL || archive.size_arr == NULL) { - ret = PRNE_INDEX_BIN_ARCHIVE_MEM_ERR; - goto END; + if (req == 0) { + return 0; } - archive.data_size = in->data_size; - archive.data = in->data; - archive.nb_binaries = arr_cnt; - memcpy(archive.arch_arr, arch_arr, arr_cnt * sizeof(prne_arch_t)); - memcpy(archive.offset_arr, offset_arr, arr_cnt * sizeof(size_t)); - memcpy(archive.size_arr, size_arr, arr_cnt * sizeof(size_t)); - - in->data = NULL; - in->data_size = 0; - *out = archive; + ctx->zs.next_out = out; + ctx->zs.avail_out = req; + switch ((pr.err = inflate(&ctx->zs, Z_SYNC_FLUSH))) { + case Z_OK: + case Z_STREAM_END: + case Z_BUF_ERROR: + pr.err = 0; + break; + default: + pr.rc = PRNE_PACK_RC_Z_ERR; + goto END; + } + if (ctx->zs.avail_out != 0) { + pr.rc = PRNE_PACK_RC_FMT_ERR; + goto END; + } END: - if (ret != PRNE_INDEX_BIN_ARCHIVE_OK) { - prne_free_bin_archive(&archive); + if (pr_out != NULL) { + *pr_out = pr; + } + if (pr.rc != PRNE_PACK_RC_OK) { + return -1; } - return ret; + return req; } -void prne_free_unpack_bin_archive_result (prne_unpack_bin_archive_result_t *r) { - prne_free(r->data); - r->data = NULL; - r->data_size = 0; - r->result = PRNE_INDEX_BIN_ARCHIVE_OK; - r->err = 0; -} +char *prne_pack_ret_tostr (const prne_pack_ret_t pr) { + const char *rc_str; + const char *err_str; + char *buf = NULL, err_buf[31]; + size_t buf_size; -void prne_free_bin_archive (prne_bin_archive_t *a) { - prne_free(a->data); - prne_free(a->arch_arr); - prne_free(a->offset_arr); - prne_free(a->size_arr); - a->nb_binaries = 0; - a->data = NULL; - a->data_size = 0; - a->arch_arr = NULL; - a->offset_arr = NULL; - a->size_arr = NULL; + switch (pr.rc) { + case PRNE_PACK_RC_OK: rc_str = "ok"; break; + case PRNE_PACK_RC_FMT_ERR: rc_str = "fmt err"; break; + case PRNE_PACK_RC_NO_BIN: rc_str = "no bin"; break; + default: rc_str = NULL; + } + if (rc_str != NULL) { + buf_size = strlen(rc_str) + 1; + buf = (char*)prne_malloc(1, buf_size); + if (buf != NULL) { + memcpy(buf, rc_str, buf_size); + } + return buf; + } + + switch (pr.rc) { + case PRNE_PACK_RC_ERRNO: + rc_str = "errno"; + err_str = strerror(pr.err); + break; + case PRNE_PACK_RC_Z_ERR: + rc_str = "zlib err"; + err_str = zError(pr.err); + break; + case PRNE_PACK_RC_MBEDTLS_ERR: + rc_str = "mbedtls err"; + mbedtls_strerror(pr.err, err_buf, sizeof(err_buf)); + err_str = err_buf; + break; + default: + errno = EINVAL; + return NULL; + } + + buf_size = strlen(rc_str) + 4 + 11 + 1 + strlen(err_str) + 1; + buf = (char*)prne_malloc(1, buf_size); + if (buf != NULL) { + if (sprintf(buf, "%s - (%d)%s", rc_str, pr.err, err_str) < 0) { + prne_free(buf); + return NULL; + } + } + return buf; } -- cgit