From 5f341e4c20767f08165776bdf559b096dc8996e9 Mon Sep 17 00:00:00 2001 From: David Timber Date: Fri, 27 Dec 2019 18:22:18 +1100 Subject: initial commit --- src/proone_pack.c | 277 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 src/proone_pack.c (limited to 'src/proone_pack.c') diff --git a/src/proone_pack.c b/src/proone_pack.c new file mode 100644 index 0000000..c257195 --- /dev/null +++ b/src/proone_pack.c @@ -0,0 +1,277 @@ +#include "proone_pack.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + + +void proone_init_bin_archive (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; +} + +void proone_init_unpack_bin_archive_result (proone_unpack_bin_archive_result_t *r) { + r->data_size = 0; + r->data = NULL; + r->raw_data_size = 0; + r->raw_data = NULL; + r->result = PROONE_UNPACK_BIN_ARCHIVE_OK; + r->err = 0; +} + +proone_unpack_bin_archive_result_t proone_unpack_bin_archive (const int fd) { + static const size_t fd_buf_size = 77, bio_buf_size = 58, z_buf_size = 4096; + + proone_unpack_bin_archive_result_t ret; + BIO *b64_bio = NULL, *mem_bio = NULL; + uint8_t fd_buf[fd_buf_size], bio_buf[bio_buf_size], z_buf[z_buf_size]; + int fd_read_size, fd_data_size, bio_write_size, bio_read_size; + int z_func_ret; + z_stream stream; + size_t z_out_size; + void *ny_buf; + bool stream_end; + size_t i; + + proone_init_unpack_bin_archive_result(&ret); + + stream.zalloc = NULL; + stream.zfree = NULL; + stream.opaque = NULL; + stream.avail_in = 0; + stream.next_in = Z_NULL; + z_func_ret = inflateInit(&stream); + if (z_func_ret != Z_OK) { + ret.result = PROONE_UNPACK_BIN_ARCHIVE_Z_ERR; + ret.err = z_func_ret; + return ret; + } + + if ((mem_bio = BIO_new(BIO_s_mem())) == NULL || (b64_bio = BIO_new(BIO_f_base64())) == NULL) { + ret.result = PROONE_UNPACK_BIN_ARCHIVE_OPENSSL_ERR; + ret.err = ERR_get_error(); + goto END; + } + BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); + BIO_push(b64_bio, mem_bio); + + stream_end = false; + do { + fd_read_size = read(fd, fd_buf, fd_buf_size); + if (fd_read_size < 0) { + ret.result = PROONE_UNPACK_BIN_ARCHIVE_ERRNO; + ret.err = errno; + goto END; + } + if (fd_read_size == 0) { + break; + } + + ny_buf = realloc(ret.raw_data, ret.raw_data_size + fd_read_size); + if (ny_buf == NULL) { + ret.result = PROONE_UNPACK_BIN_ARCHIVE_MEM_ERR; + ret.err = errno; + goto END; + } + ret.raw_data = (uint8_t*)ny_buf; + memcpy(ret.raw_data + ret.raw_data_size, fd_buf, fd_read_size); + ret.raw_data_size += fd_read_size; + + // remove white spaces + fd_data_size = fd_read_size; + for (i = 0; i < fd_data_size; ) { + if (isspace(fd_buf[i])) { + if (i + 1 >= fd_data_size) { + // last trailing whitespace + fd_data_size -= 1; + break; + } + memmove(fd_buf + i, fd_buf + i + 1, fd_data_size - i - 1); + fd_data_size -= 1; + } + else { + i += 1; + } + } + + if (fd_data_size > 0) { + BIO_reset(mem_bio); + bio_write_size = BIO_write(mem_bio, fd_buf, fd_data_size); + if (bio_write_size != fd_data_size) { + ret.result = PROONE_UNPACK_BIN_ARCHIVE_MEM_ERR; + goto END; + } + + bio_read_size = BIO_read(b64_bio, bio_buf, (int)bio_buf_size); + if (bio_read_size < 0) { + ret.result = PROONE_UNPACK_BIN_ARCHIVE_OPENSSL_ERR; + ret.err = ERR_get_error(); + goto END; + } + + if (bio_read_size > 0) { + stream.avail_in = bio_read_size; + stream.next_in = bio_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 = PROONE_UNPACK_BIN_ARCHIVE_Z_ERR; + ret.err = z_func_ret; + goto END; + } + + z_out_size = z_buf_size - stream.avail_out; + ny_buf = realloc(ret.data, ret.data_size + z_out_size); + if (ny_buf == NULL) { + ret.result = PROONE_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); + } + } + } while (!stream_end); + +END: + inflateEnd(&stream); + BIO_free(b64_bio); + BIO_free(mem_bio); + + if (ret.result != PROONE_UNPACK_BIN_ARCHIVE_OK) { + free(ret.data); + free(ret.raw_data); + ret.data = NULL; + ret.data_size = 0; + ret.raw_data = NULL; + ret.raw_data_size = 0; + } + + return ret; +} + +proone_index_bin_archive_result_code_t proone_index_bin_archive (proone_unpack_bin_archive_result_t *in, bin_archive_t *out) { + proone_index_bin_archive_result_code_t ret = PROONE_INDEX_BIN_ARCHIVE_OK; + size_t buf_pos = 0, arr_cnt = 0, offset_arr[NB_PROONE_ARCH], size_arr[NB_PROONE_ARCH], i; + proone_arch_t arch; + uint32_t bin_size; + proone_arch_t arch_arr[NB_PROONE_ARCH]; + bin_archive_t archive; + uint8_t *out_buf; + void *ny_buf; + + memset(arch_arr, 0, sizeof(proone_arch_t) * NB_PROONE_ARCH); + memset(offset_arr, 0, sizeof(size_t) * NB_PROONE_ARCH); + memset(size_arr, 0, sizeof(size_t) * NB_PROONE_ARCH); + proone_init_bin_archive(&archive); + + do { + if (buf_pos + 4 >= in->data_size || arr_cnt >= NB_PROONE_ARCH) { + ret = PROONE_INDEX_BIN_ARCHIVE_FMT_ERR; + goto END; + } + + arch = (proone_arch_t)in->data[buf_pos]; + bin_size = + ((uint32_t)in->data[buf_pos + 1] << 16) | + ((uint32_t)in->data[buf_pos + 2] << 8) | + (uint32_t)in->data[buf_pos + 3]; + if (proone_arch2str(arch) == NULL || bin_size == 0 || buf_pos + 4 + bin_size > in->data_size) { + ret = PROONE_INDEX_BIN_ARCHIVE_FMT_ERR; + goto END; + } + + 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); + + out_buf = (uint8_t*)malloc(sizeof(proone_arch_t) * arr_cnt + sizeof(size_t*) * arr_cnt + sizeof(size_t*) * arr_cnt); + if (out_buf == NULL) { + ret = PROONE_INDEX_BIN_ARCHIVE_MEM_ERR; + goto END; + } + archive.arch_arr = (proone_arch_t*)out_buf; + archive.offset_arr = (size_t*)(out_buf + sizeof(proone_arch_t) * arr_cnt); + archive.size_arr = (size_t*)(out_buf + sizeof(proone_arch_t) * arr_cnt + sizeof(size_t*) * arr_cnt); + + archive.nb_binaries = arr_cnt; + buf_pos = 0; + for (i = 0; i < arr_cnt; i += 1) { + memmove(in->data + buf_pos, in->data + offset_arr[i], size_arr[i]); + archive.arch_arr[i] = arch_arr[i]; + archive.offset_arr[i] = buf_pos; + archive.size_arr[i] = size_arr[i]; + buf_pos += size_arr[i]; + } + + ny_buf = realloc(in->data, buf_pos); + if (ny_buf == NULL) { + ret = PROONE_INDEX_BIN_ARCHIVE_MEM_ERR; + goto END; + } + archive.data = (uint8_t*)ny_buf; + archive.data_size = buf_pos; + + *out = archive; + in->data = NULL; + in->data_size = 0; + +END: + if (ret != PROONE_INDEX_BIN_ARCHIVE_OK) { + proone_free_bin_archive(&archive); + } + + return ret; +} + +void proone_free_unpack_bin_archive_result (proone_unpack_bin_archive_result_t *r) { + free(r->data); + free(r->raw_data); + r->data = NULL; + r->data_size = 0; + r->raw_data = NULL; + r->raw_data_size = 0; + r->result = PROONE_INDEX_BIN_ARCHIVE_OK; + r->err = 0; +} + +void proone_free_bin_archive (bin_archive_t *a) { + free(a->data); + free(a->arch_arr); + a->nb_binaries = 0; + a->data_size = 0; + a->arch_arr = NULL; + a->offset_arr = NULL; + a->size_arr = NULL; +} -- cgit