From 2df5066a9741e9534d13bc422dad69bb6a2c12ce Mon Sep 17 00:00:00 2001 From: jikai Date: Mon, 28 Aug 2023 12:59:08 +0000 Subject: [PATCH 07/22] Fix empty pointer and overflow Signed-off-by: jikai --- src/buffer.c | 4 + src/conf.c | 63 +++++++++++-- src/lcrcontainer.c | 135 ++------------------------- src/lcrcontainer.h | 40 -------- src/lcrcontainer_execute.c | 30 ++++++ src/lcrcontainer_extend.c | 144 ++++------------------------- src/lcrcontainer_extend.h | 11 --- src/utils.c | 5 + tests/fuzz/log_fuzz.cc | 2 +- third_party/go_crc64.c | 6 +- third_party/libocispec/common_c.py | 58 +++++++++--- third_party/libocispec/common_h.py | 4 + third_party/libocispec/sources.py | 26 ++++-- 13 files changed, 192 insertions(+), 336 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index 39e0360..fb9e153 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -158,6 +158,10 @@ static int buffer_append(Buffer *buf, const char *append, size_t length) return -1; } + if (length == SIZE_MAX) { + return -1; + } + desired_length = length + 1; if (!buffer_has_space(buf, desired_length)) { if (buffer_grow(buf, desired_length) != 0) { diff --git a/src/conf.c b/src/conf.c index 2b02887..10214f0 100644 --- a/src/conf.c +++ b/src/conf.c @@ -638,6 +638,10 @@ static int trans_oci_process_prlimit(const defs_process *proc, struct lcr_list * for (i = 0; i < proc->rlimits_len; i++) { defs_process_rlimits_element *lr = proc->rlimits[i]; + if (lr == NULL) { + continue; + } + char buf_key[30] = { 0 }; char buf_value[60] = { 0 }; size_t j; @@ -750,6 +754,10 @@ struct lcr_list *trans_oci_process(const defs_process *proc) { struct lcr_list *conf = NULL; + if (proc == NULL) { + return NULL; + } + conf = lcr_util_common_calloc_s(sizeof(struct lcr_list)); if (conf == NULL) { return NULL; @@ -1093,7 +1101,8 @@ bool is_system_container(const oci_runtime_spec *container) { size_t i = 0; for (i = 0; container->annotations != NULL && i < container->annotations->len; i++) { - if (strcmp(container->annotations->keys[i], "system.container") == 0) { + if (container->annotations->keys[i] != NULL && + strcmp(container->annotations->keys[i], "system.container") == 0) { return true; } } @@ -1104,7 +1113,8 @@ static bool is_external_rootfs(const oci_runtime_spec *container) { size_t i = 0; for (i = 0; container->annotations != NULL && i < container->annotations->len; i++) { - if (strcmp(container->annotations->keys[i], "external.rootfs") == 0) { + if (container->annotations->keys[i] != NULL && + strcmp(container->annotations->keys[i], "external.rootfs") == 0) { return true; } } @@ -1166,8 +1176,14 @@ struct lcr_list *trans_oci_mounts(const oci_runtime_spec *c) struct lcr_list *node = NULL; defs_mount *tmp = NULL; size_t i; - bool system_container = is_system_container(c); - bool external_rootfs = is_external_rootfs(c); + bool system_container = false; + bool external_rootfs = false; + + if (c == NULL) { + return NULL; + } + system_container = is_system_container(c); + external_rootfs = is_external_rootfs(c); conf = lcr_util_common_calloc_s(sizeof(*conf)); if (conf == NULL) { @@ -1177,7 +1193,7 @@ struct lcr_list *trans_oci_mounts(const oci_runtime_spec *c) for (i = 0; i < c->mounts_len; i++) { tmp = c->mounts[i]; - if (tmp->type == NULL) { + if (tmp == NULL || tmp->type == NULL) { goto out_free; } @@ -1206,6 +1222,10 @@ static int trans_one_oci_id_mapping(struct lcr_list *conf, const char *typ, cons char buf_value[DEFAULT_BUF_LEN] = { 0 }; char subid[ID_MAP_LEN] = { 0 }; + if (id == NULL) { + return -1; + } + nret = snprintf(buf_value, sizeof(buf_value), "%s %u %u %u", typ, id->container_id, id->host_id, id->size); if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { return -1; @@ -1570,6 +1590,10 @@ static int trans_resources_devices_v1(const defs_resources *res, struct lcr_list for (i = 0; i < res->devices_len; i++) { defs_device_cgroup *lrd = res->devices[i]; + if (lrd == NULL) { + continue; + } + if (trans_resources_devices_ret(lrd, buf_value, sizeof(buf_value)) < 0) { goto out; } @@ -2006,6 +2030,10 @@ static int trans_resources_devices_v2(const defs_resources *res, struct lcr_list for (i = 0; i < res->devices_len; i++) { defs_device_cgroup *lrd = res->devices[i]; + if (lrd == NULL) { + continue; + } + if (trans_resources_devices_ret(lrd, buf_value, sizeof(buf_value)) < 0) { goto out; } @@ -2492,7 +2520,7 @@ static struct lcr_list *trans_oci_namespaces(const oci_runtime_config_linux *l) char *ns_name = NULL; ns = l->namespaces[i]; - if (ns->type == NULL || ns->path == NULL) { + if (ns == NULL || ns->type == NULL || ns->path == NULL) { continue; } @@ -2807,6 +2835,12 @@ static int seccomp_append_rule(const defs_syscall *syscall, size_t i, Buffer *bu ret = -1; goto out; } + + if (strlen(syscall->names[i]) > SIZE_MAX - strlen(action) - 2) { + ERROR("Out of range"); + ret = -1; + goto out; + } if (buffer_nappendf(buffer, strlen(syscall->names[i]) + strlen(action) + 2, "%s %s", syscall->names[i], action)) { ERROR("Failed to append syscall name and action\n"); ret = -1; @@ -2819,6 +2853,15 @@ static int seccomp_append_rule(const defs_syscall *syscall, size_t i, Buffer *bu ret = -1; goto out; } + + /* Appending content is syscall->args[j]->op plus + * three unsigned numbers(which length is no more than 20 * 3) + */ + if (strlen(syscall->args[j]->op) > SIZE_MAX - 20 * 3) { + ERROR("Out of range"); + ret = -1; + goto out; + } if (buffer_nappendf(buffer, 20 * 3 + strlen(syscall->args[j]->op), " [%u,%llu,%s,%llu]", syscall->args[j]->index, syscall->args[j]->value, syscall->args[j]->op, syscall->args[j]->value_two)) { @@ -3032,6 +3075,10 @@ struct lcr_list *trans_oci_linux(const oci_runtime_config_linux *l, char **secco int ret = 0; struct lcr_list *tmp = NULL; + if (l == NULL) { + return NULL; + } + struct lcr_list *conf = lcr_util_common_calloc_s(sizeof(*conf)); if (conf == NULL) { return NULL; @@ -3114,6 +3161,10 @@ struct lcr_list *trans_annotations(const json_map_string_string *anno) size_t len; int ret = 0; + if (anno == NULL) { + return NULL; + } + struct lcr_list *conf = lcr_util_common_calloc_s(sizeof(*conf)); if (conf == NULL) { return NULL; diff --git a/src/lcrcontainer.c b/src/lcrcontainer.c index ca587e4..f65f570 100644 --- a/src/lcrcontainer.c +++ b/src/lcrcontainer.c @@ -44,52 +44,6 @@ #include "utils.h" #include "oci_runtime_spec.h" -/* - * Free lcr_container_info array returned by lcr_list_{active,all}_containers - */ -void lcr_containers_info_free(struct lcr_container_info **info_arr, size_t size) -{ - size_t i = 0; - struct lcr_container_info *in = NULL; - - if (info_arr == NULL) { - return; - } - if (size == 0) { - return; - } - for (i = 0, in = *info_arr; i < size; i++, in++) { - free(in->interface); - free(in->ipv4); - free(in->ipv6); - free(in->name); - free(in->state); - } - free(*info_arr); - *info_arr = NULL; -} - -/* - * Free lcr_container_info returned lcr_container_info_get - */ -void lcr_container_info_free(struct lcr_container_info *info) -{ - if (info == NULL) { - return; - } - free(info->interface); - info->interface = NULL; - free(info->ipv4); - info->ipv4 = NULL; - free(info->ipv6); - info->ipv6 = NULL; - free(info->name); - info->name = NULL; - free(info->state); - info->state = NULL; - free(info); -} - static inline bool is_container_exists(struct lxc_container *c) { return c->is_defined(c); @@ -100,85 +54,6 @@ static inline bool is_container_can_control(struct lxc_container *c) return c->may_control(c); } -/* - * Get one container info for a given name and lcrpath. - * return struct of container info, or NULL on error. - */ -struct lcr_container_info *lcr_container_info_get(const char *name, const char *lcrpath) -{ - int nret = -1; - struct lcr_container_info *info = NULL; - const char *st = NULL; - bool run_flag = false; - - struct lxc_container *c = lxc_container_without_config_new(name, lcrpath); - if (c == NULL) { - return NULL; - } - - if (!is_container_exists(c)) { - goto put_and_finish; - } - - st = c->state(c); - if (st == NULL) { - st = "UNKNOWN"; - } - run_flag = (strcmp(st, "STOPPED") != 0); - - /* Now it makes sense to allocate memory */ - info = lcr_util_common_calloc_s(sizeof(*info)); - if (info == NULL) { - nret = -1; - goto put_and_finish; - } - info->init = -1; - info->running = run_flag; - info->name = lcr_util_strdup_s(name); - info->state = lcr_util_strdup_s(st); - if (run_flag) { - info->init = c->init_pid(c); - } - - nret = 0; -put_and_finish: - lxc_container_put(c); - if (nret != 0) { - lcr_container_info_free(info); - info = NULL; - } - return info; -} - -/* - * Get a complete list of all containers for a given lcrpath. - * return Number of containers, or -1 on error. - **/ -int lcr_list_all_containers(const char *lcrpath, struct lcr_container_info **info_arr) -{ - char **container = NULL; - int n = 0; - int nret = -1; - size_t info_size = 0; - const char *path = lcrpath ? lcrpath : LCRPATH; - - clear_error_message(&g_lcr_error); - n = list_all_containers(path, &container, NULL); - if (n == -1) { - n = 0; - } - - nret = lcr_containers_info_get(path, info_arr, &info_size, container, n); - if (info_arr == NULL && nret == 0) { - return -1; - } else if (info_arr == NULL || nret == -1) { - lcr_containers_info_free(info_arr, info_size); - return -1; - } - - return (int)info_size; -} - static int create_partial(const struct lxc_container *c) { int fd = 0; @@ -276,6 +151,16 @@ bool lcr_create(const char *name, const char *lcrpath, void *oci_config) const char *tmp_path = lcrpath ? lcrpath : LCRPATH; oci_runtime_spec *oci_spec = (oci_runtime_spec *)oci_config; + if (name == NULL) { + ERROR("Missing container name"); + return false; + } + + if (oci_spec == NULL) { + ERROR("Empty oci config"); + return false; + } + clear_error_message(&g_lcr_error); isula_libutils_set_log_prefix(name); diff --git a/src/lcrcontainer.h b/src/lcrcontainer.h index 5cb3647..b065641 100644 --- a/src/lcrcontainer.h +++ b/src/lcrcontainer.h @@ -46,24 +46,6 @@ struct lcr_console_config { char *log_file_size; }; -/* -* Store lcr container info -*/ -struct lcr_container_info { - /* Name of container. */ - char *name; - /* State of container. */ - char *state; - /* Interface of container. */ - char *interface; - char *ipv4; - char *ipv6; - pid_t init; - double ram; - double swap; - bool running; -}; - struct blkio_stats { uint64_t read; uint64_t write; @@ -129,28 +111,6 @@ struct lcr_cgroup_resources { int64_t cpurt_runtime; }; -/* -* Get one container info for a given lcrpath. -* return struct of container info, or NULL on error. -*/ -struct lcr_container_info *lcr_container_info_get(const char *name, const char *lcrpath); - -/* -* Free lcr_container_info returned lcr_container_info_get -*/ -void lcr_container_info_free(struct lcr_container_info *info); - -/* -* Get a complete list of all containers for a given lcrpath. -* return Number of containers, or -1 on error. -*/ -int lcr_list_all_containers(const char *lcrpath, struct lcr_container_info **info_arr); - -/* -* Free lcr_container_info array returned by lcr_list_{active,all}_containers -*/ -void lcr_containers_info_free(struct lcr_container_info **info_arr, size_t size); - /* * Create a container * param name : container name diff --git a/src/lcrcontainer_execute.c b/src/lcrcontainer_execute.c index 4c49a28..b924254 100644 --- a/src/lcrcontainer_execute.c +++ b/src/lcrcontainer_execute.c @@ -749,6 +749,11 @@ bool do_update(struct lxc_container *c, const char *name, const char *lcrpath, s { bool bret = false; + if (c == NULL) { + ERROR("Invalid arg c"); + return bret; + } + // If container is not running, update config file is enough, // resources will be updated when the container is started again. // If container is running (including paused), we need to update configs @@ -773,6 +778,16 @@ void do_lcr_state(struct lxc_container *c, struct lcr_container_state *lcs) { struct lxc_container_metrics lxc_metrics = { 0 }; + if (c == NULL) { + ERROR("Invalid argument c"); + return; + } + + if (lcs == NULL) { + ERROR("Invalid argument lcs"); + return; + } + clear_error_message(&g_lcr_error); (void)memset(lcs, 0x00, sizeof(struct lcr_container_state)); @@ -925,6 +940,16 @@ bool do_attach(const char *name, const char *path, const struct lcr_exec_request int pipefd[2] = {-1, -1}; int status = 0; + if (request == NULL) { + ERROR("Invalid request"); + return false; + } + + if (exit_code == NULL) { + ERROR("Invalid exit code"); + return false; + } + if (pipe(pipefd) != 0) { ERROR("Failed to create pipe\n"); return false; @@ -988,6 +1013,11 @@ void execute_lxc_start(const char *name, const char *path, const struct lcr_star size_t i = 0; int nret = 0; + if (request == NULL) { + COMMAND_ERROR("Invalid request"); + exit(EXIT_FAILURE); + } + if (lcr_util_check_inherited(true, -1) != 0) { COMMAND_ERROR("Close inherited fds failed"); } diff --git a/src/lcrcontainer_extend.c b/src/lcrcontainer_extend.c index e03c212..645f159 100644 --- a/src/lcrcontainer_extend.c +++ b/src/lcrcontainer_extend.c @@ -422,74 +422,6 @@ cleanup: return NULL; } -static struct lcr_container_info *info_new(struct lcr_container_info **info, size_t *size) -{ - struct lcr_container_info *m = NULL; - struct lcr_container_info *n = NULL; - size_t length = 0; - int nret = 0; - - if (*size > SIZE_MAX / sizeof(struct lcr_container_info) - 1) { - return NULL; - } - - length = (*size + 1) * sizeof(struct lcr_container_info); - - nret = lcr_mem_realloc((void **)&n, length, (void *)(*info), (*size) * sizeof(struct lcr_container_info)); - if (nret < 0) { - return NULL; - } - - *info = n; - m = *info + *size; - (*size)++; - - // *INDENT-OFF* - *m = (struct lcr_container_info) { - .name = NULL, .state = NULL, .interface = NULL, .ipv4 = NULL, .ipv6 = NULL, .ram = 0.0, .swap = 0.0, .init = -1 - }; - // *INDENT-ON* - return m; -} - -static void free_arr(char **array, size_t size) -{ - size_t i; - for (i = 0; i < size; i++) { - free(array[i]); - array[i] = NULL; - } - free(array); -} - -/* - * Get a complete list of active containers for a given lcrpath. - * return Number of containers, or -1 on error. - **/ -int lcr_list_active_containers(const char *lcrpath, struct lcr_container_info **info_arr) -{ - char **c = NULL; - int n = 0; - int nret = -1; - size_t info_size = 0; - const char *path = lcrpath ? lcrpath : LCRPATH; - - n = list_active_containers(path, &c, NULL); - if (n == -1) { - n = 0; - } - - nret = lcr_containers_info_get(path, info_arr, &info_size, c, n); - if ((info_arr == NULL) && nret == 0) { - return -1; - } else if ((info_arr == NULL) || nret == -1) { - lcr_containers_info_free(info_arr, info_size); - return -1; - } - - return (int)info_size; -} - bool lcr_delete_with_force(const char *name, const char *lcrpath, bool force) { struct lxc_container *c = NULL; @@ -560,61 +492,6 @@ void lcr_free_config(struct lcr_list *lcr_conf) } } -int lcr_containers_info_get(const char *lcrpath, struct lcr_container_info **info, size_t *size, char **containers, - int num) -{ - struct lcr_container_info *in = NULL; - struct lxc_container *c = NULL; - int i; - int nret = -1; - - if ((lcrpath == NULL) || num == 0) { - goto err_out; - } - - for (i = 0; i < num; i++) { - const char *st = NULL; - const char *name = containers[i]; - bool run_flag = true; - if (name == NULL) { - continue; - } - - c = lxc_container_without_config_new(name, lcrpath); - if (c == NULL) { - continue; - } - - if (!c->is_defined(c)) { - goto put_container; - } - - st = c->state(c); - if (st == NULL) { - st = "UNKNOWN"; - } - run_flag = (strcmp(st, "STOPPED") != 0); - - /* Now it makes sense to allocate memory */ - in = info_new(info, size); - if (in == NULL) { - goto put_container; - } - in->running = run_flag; - in->name = lcr_util_strdup_s(name); - in->state = lcr_util_strdup_s(st); - if (run_flag) { - in->init = c->init_pid(c); - } -put_container: - lxc_container_put(c); - } - nret = 0; -err_out: - free_arr(containers, (size_t)num); - return nret; -} - /* * Transform container JSON into oci_runtime_spec struct */ @@ -624,6 +501,11 @@ bool container_parse(const char *oci_filename, const char *oci_json_data, oci_ru parser_error err = NULL; bool ret = true; + if (container == NULL) { + ERROR("Invalid container arg"); + return false; + } + if (oci_json_data == NULL) { *container = oci_runtime_spec_parse_file(oci_filename, &ctx, &err); } else { @@ -680,6 +562,11 @@ struct lcr_list *lcr_oci2lcr(const struct lxc_container *c, oci_runtime_spec *co { struct lcr_list *lcr_conf = NULL; + if (container == NULL) { + ERROR("Invalid arguments"); + return NULL; + } + lcr_conf = lcr_util_common_calloc_s(sizeof(*lcr_conf)); if (lcr_conf == NULL) { goto out_free; @@ -765,6 +652,10 @@ static char *escape_string_encode(const char *src) return NULL; } + if (len > (SIZE_MAX - 1) / 2) { + return NULL; + } + dst = lcr_util_common_calloc_s(2 * len + 1); if (dst == NULL) { ERROR("Out of memory"); @@ -863,7 +754,7 @@ cleanup: return ret; } -char *lcr_get_bundle(const char *lcrpath, const char *name) +static char *lcr_get_bundle(const char *lcrpath, const char *name) { size_t len = 0; int nret = 0; @@ -921,6 +812,11 @@ bool lcr_save_spec(const char *name, const char *lcrpath, const struct lcr_list return bret; } + if (lcr_conf == NULL) { + ERROR("Empty lcr conf"); + return bret; + } + bundle = lcr_get_bundle(path, name); if (bundle == NULL) { goto out_free; diff --git a/src/lcrcontainer_extend.h b/src/lcrcontainer_extend.h index 981a2bb..f524a4a 100644 --- a/src/lcrcontainer_extend.h +++ b/src/lcrcontainer_extend.h @@ -44,12 +44,6 @@ struct lcr_list; } \ } while (0); -/* - * Get a complete list of active containers for a given lcrpath. - * return Number of containers, or -1 on error. - */ -int lcr_list_active_containers(const char *lcrpath, struct lcr_container_info **info_arr); - /* * Delete a container * param name : container name, required. @@ -82,11 +76,6 @@ struct lcr_list *lcr_oci2lcr(const struct lxc_container *c, oci_runtime_spec *co */ bool lcr_save_spec(const char *name, const char *lcrpath, const struct lcr_list *lcr_conf, const char *seccomp_conf); -int lcr_containers_info_get(const char *lcrpath, struct lcr_container_info **info, size_t *size, char **containers, - int num); - -char *lcr_get_bundle(const char *lcrpath, const char *name); - bool translate_spec(const struct lxc_container *c, oci_runtime_spec *container); #ifdef __cplusplus diff --git a/src/utils.c b/src/utils.c index 4b123bb..d1271dd 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1287,6 +1287,11 @@ out: /* swap in oci is memoy+swap, so here we need to get real swap */ int lcr_util_get_real_swap(int64_t memory, int64_t memory_swap, int64_t *swap) { + if (swap == NULL) { + ERROR("empty swap pointer"); + return -1; + } + if (memory == -1 && memory_swap == 0) { *swap = -1; // -1 is max return 0; diff --git a/tests/fuzz/log_fuzz.cc b/tests/fuzz/log_fuzz.cc index a8f80d4..4128ff6 100644 --- a/tests/fuzz/log_fuzz.cc +++ b/tests/fuzz/log_fuzz.cc @@ -40,7 +40,6 @@ extern "C" void testLog(struct isula_libutils_log_config *conf) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - const char *default_name = "iSula"; struct isula_libutils_log_config tconf = {0}; std::string testData(reinterpret_cast(data), size); std::vector ret_vec; @@ -67,6 +66,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) tconf.driver = ret_vec[4].c_str(); } } else { + const char *default_name = "iSula"; isula_libutils_default_log_config(default_name, &tconf); } diff --git a/third_party/go_crc64.c b/third_party/go_crc64.c index 44d0a75..c78ac85 100644 --- a/third_party/go_crc64.c +++ b/third_party/go_crc64.c @@ -32,10 +32,9 @@ isula_crc_table_t g_iso_crc_table; static void make_table(isula_crc_table_t *tab, uint64_t poly) { uint64_t i, j; - uint64_t t; for (i = 0; i < CRC_COL_LEN; i++) { - t = i; + uint64_t t = i; for (j = 0; j < CRC_ROW_LEN; j++) { if ((t & 1) == 1) { t = (t >> 1) ^ poly; @@ -50,10 +49,9 @@ static void make_table(isula_crc_table_t *tab, uint64_t poly) static void make_crc_table(isula_crc_table_t *tab) { uint64_t i, j; - uint64_t crc; for (i = 0; i < CRC_COL_LEN; i++) { - crc = tab->table[0][i]; + uint64_t crc = tab->table[0][i]; for (j = 1; j < CRC_ROW_LEN; j++) { crc = tab->table[0][(crc&0xff)] ^ (crc >> 8); tab->table[j][i] = crc; diff --git a/third_party/libocispec/common_c.py b/third_party/libocispec/common_c.py index 968d5d2..1207b72 100644 --- a/third_party/libocispec/common_c.py +++ b/third_party/libocispec/common_c.py @@ -42,6 +42,13 @@ CODE = '''// Auto generated file. Do not edit! # define MAX_NUM_STR_LEN 21 +#if __WORDSIZE == 64 +// current max user memory for 64-machine is 2^47 B +#define MAX_MEMORY_SIZE ((size_t)1 << 47) +#else +// current max user memory for 32-machine is 2^31 B +#define MAX_MEMORY_SIZE ((size_t)1 << 31) +#endif static yajl_gen_status gen_yajl_val (yajl_val obj, yajl_gen g, parser_error *err); @@ -205,6 +212,27 @@ void *safe_malloc(size_t size) { return ret; } +void *smart_safe_malloc(size_t count, size_t extra, size_t unit_size) { + void *ret = NULL; + if (unit_size == 0) { + abort(); + } + + if (extra > MAX_MEMORY_SIZE || count > MAX_MEMORY_SIZE - extra) { + abort(); + } + + if (count + extra == 0 || count + extra > (MAX_MEMORY_SIZE / unit_size)) { + abort(); + } + + ret = calloc(count + extra, unit_size); + if (ret == NULL) { + abort(); + } + return ret; +} + int common_safe_double(const char *numstr, double *converted) { char *err_str = NULL; double d; @@ -557,8 +585,8 @@ json_map_int_int *make_json_map_int_int(yajl_val src, const struct parser_contex size_t len = YAJL_GET_OBJECT(src)->len; ret = safe_malloc(sizeof(*ret)); ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(int)); - ret->values = safe_malloc((len + 1) * sizeof(int)); + ret->keys = smart_safe_malloc(len, 1, sizeof(int)); + ret->values = smart_safe_malloc(len, 1, sizeof(int)); for (i = 0; i < len; i++) { const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; @@ -695,8 +723,8 @@ json_map_int_bool *make_json_map_int_bool(yajl_val src, const struct parser_cont size_t len = YAJL_GET_OBJECT(src)->len; ret = safe_malloc(sizeof(*ret)); ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(int)); - ret->values = safe_malloc((len + 1) * sizeof(bool)); + ret->keys = smart_safe_malloc(len, 1, sizeof(int)); + ret->values = smart_safe_malloc(len, 1, sizeof(bool)); for (i = 0; i < len; i++) { const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; @@ -829,8 +857,8 @@ json_map_int_string *make_json_map_int_string(yajl_val src, const struct parser_ size_t len = YAJL_GET_OBJECT(src)->len; ret = safe_malloc(sizeof(*ret)); ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(int)); - ret->values = safe_malloc((len + 1) * sizeof(char *)); + ret->keys = smart_safe_malloc(len, 1, sizeof(int)); + ret->values = smart_safe_malloc(len, 1, sizeof(char *)); for (i = 0; i < len; i++) { const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; @@ -951,8 +979,8 @@ json_map_string_int *make_json_map_string_int(yajl_val src, const struct parser_ size_t len = YAJL_GET_OBJECT(src)->len; ret = safe_malloc(sizeof(*ret)); ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(char *)); - ret->values = safe_malloc((len + 1) * sizeof(int)); + ret->keys = smart_safe_malloc(len, 1, sizeof(char *)); + ret->values = smart_safe_malloc(len, 1, sizeof(int)); for (i = 0; i < len; i++) { const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; @@ -1069,8 +1097,8 @@ json_map_string_int64 *make_json_map_string_int64(yajl_val src, const struct par size_t len = YAJL_GET_OBJECT(src)->len; ret = safe_malloc(sizeof(*ret)); ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(char *)); - ret->values = safe_malloc((len + 1) * sizeof(int64_t)); + ret->keys = smart_safe_malloc(len, 1, sizeof(char *)); + ret->values = smart_safe_malloc(len, 1, sizeof(int64_t)); for (i = 0; i < len; i++) { const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; @@ -1188,8 +1216,8 @@ json_map_string_bool *make_json_map_string_bool(yajl_val src, const struct parse size_t len = YAJL_GET_OBJECT(src)->len; ret = safe_malloc(sizeof(*ret)); ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(char *)); - ret->values = safe_malloc((len + 1) * sizeof(bool)); + ret->keys = smart_safe_malloc(len, 1, sizeof(char *)); + ret->values = smart_safe_malloc(len, 1, sizeof(bool)); for (i = 0; i < len; i++) { const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; @@ -1303,8 +1331,8 @@ json_map_string_string *make_json_map_string_string(yajl_val src, const struct p size_t len = YAJL_GET_OBJECT(src)->len; ret = safe_malloc(sizeof(*ret)); ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(char *)); - ret->values = safe_malloc((len + 1) * sizeof(char *)); + ret->keys = smart_safe_malloc(len, 1, sizeof(char *)); + ret->values = smart_safe_malloc(len, 1, sizeof(char *)); for (i = 0; i < len; i++) { const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; @@ -1442,7 +1470,7 @@ char *json_marshal_string(const char *str, size_t strlen, const struct parser_co goto free_out; } - json_buf = safe_malloc(gen_len + 1); + json_buf = smart_safe_malloc(gen_len, 1, 1); (void)memcpy(json_buf, gen_buf, gen_len); json_buf[gen_len] = '\\0'; diff --git a/third_party/libocispec/common_h.py b/third_party/libocispec/common_h.py index 02c689d..a5d3047 100644 --- a/third_party/libocispec/common_h.py +++ b/third_party/libocispec/common_h.py @@ -89,6 +89,8 @@ extern "C" { return stat; \\ } +#define JSON_MAX_SIZE (10LL * 1024LL * 1024LL) + typedef char *parser_error; struct parser_context { @@ -108,6 +110,8 @@ yajl_val get_val(yajl_val tree, const char *name, yajl_type type); void *safe_malloc(size_t size); +void *smart_safe_malloc(size_t count, size_t extra, size_t unit_size); + int common_safe_double(const char *numstr, double *converted); int common_safe_uint8(const char *numstr, uint8_t *converted); diff --git a/third_party/libocispec/sources.py b/third_party/libocispec/sources.py index 88f83d5..56b594b 100644 --- a/third_party/libocispec/sources.py +++ b/third_party/libocispec/sources.py @@ -59,10 +59,10 @@ def parse_map_string_obj(obj, c_file, prefix, obj_typename): c_file.write(' if (YAJL_GET_OBJECT(tree) != NULL && YAJL_GET_OBJECT(tree)->len > 0) {\n') c_file.write(' size_t i;\n') c_file.write(' ret->len = YAJL_GET_OBJECT(tree)->len;\n') - c_file.write(' ret->keys = safe_malloc((YAJL_GET_OBJECT(tree)->len + 1) ' \ - '* sizeof(*ret->keys));\n') - c_file.write(' ret->%s = safe_malloc((YAJL_GET_OBJECT(tree)->len + 1) ' \ - '* sizeof(*ret->%s));\n' % (child.fixname, child.fixname)) + c_file.write(' ret->keys = smart_safe_malloc(YAJL_GET_OBJECT(tree)->len, 1, ' \ + 'sizeof(*ret->keys));\n') + c_file.write(' ret->%s = smart_safe_malloc(YAJL_GET_OBJECT(tree)->len, 1, ' \ + 'sizeof(*ret->%s));\n' % (child.fixname, child.fixname)) c_file.write(' for (i = 0; i < YAJL_GET_OBJECT(tree)->len; i++) {\n') c_file.write(' const char *tmpkey = YAJL_GET_OBJECT(tree)->keys[i];\n') c_file.write(' ret->keys[i] = safe_strdup(tmpkey ? tmpkey : "");\n') @@ -132,8 +132,8 @@ def parse_obj_type(obj, c_file, prefix, obj_typename): ' YAJL_GET_ARRAY(tmp)->len > 0) {\n') c_file.write(' size_t i;\n') c_file.write(' ret->%s_len = YAJL_GET_ARRAY(tmp)->len;\n' % (obj.fixname)) - c_file.write(' ret->%s = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) ' \ - '* sizeof(*ret->%s));\n' % (obj.fixname, obj.fixname)) + c_file.write(' ret->%s = smart_safe_malloc(YAJL_GET_ARRAY(tmp)->len, 1, ' \ + 'sizeof(*ret->%s));\n' % (obj.fixname, obj.fixname)) c_file.write(' for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) {\n') c_file.write(' yajl_val val = YAJL_GET_ARRAY(tmp)->values[i];\n') c_file.write(' ret->%s[i] = make_%s(val, ctx, err);\n' \ @@ -166,8 +166,8 @@ def parse_obj_type(obj, c_file, prefix, obj_typename): c_file.write(' size_t i;\n') c_file.write(' ret->%s_len = YAJL_GET_ARRAY(tmp)->len;\n' % (obj.fixname)) c_file.write( - ' ret->%s = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) *' \ - ' sizeof(*ret->%s));\n' % (obj.fixname, obj.fixname)) + ' ret->%s = smart_safe_malloc(YAJL_GET_ARRAY(tmp)->len, 1, ' \ + 'sizeof(*ret->%s));\n' % (obj.fixname, obj.fixname)) c_file.write(' for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) {\n') read_val_generator(c_file, 4, 'YAJL_GET_ARRAY(tmp)->values[i]', \ "ret->%s[i]" % obj.fixname, obj.subtyp, obj.origname, obj_typename) @@ -891,7 +891,7 @@ def get_c_epilog(c_file, prefix, typ): alen = YAJL_GET_ARRAY(tree)->len; if (alen == 0) return NULL; - ptr = safe_malloc((alen + 1) * sizeof(%s_element *)); + ptr = smart_safe_malloc(alen, 1, sizeof(%s_element *)); for (i = 0; i < alen; i++) { yajl_val val = YAJL_GET_ARRAY(tree)->values[i]; ptr[i] = make_%s_element(val, ctx, err); @@ -1001,6 +1001,12 @@ yajl_gen_status gen_%s(yajl_gen g, const %s_element **ptr, size_t len, const str return NULL; *err = NULL; + if (strlen(jsondata) >= JSON_MAX_SIZE) { + if (asprintf(err, "cannot parse the data with length exceeding %%llu", JSON_MAX_SIZE) < 0) { + *err = safe_strdup("error allocating memory"); + } + return NULL; + } if (ctx == NULL) { ctx = (const struct parser_context *)(&tmp_ctx); } @@ -1049,7 +1055,7 @@ yajl_gen_status gen_%s(yajl_gen g, const %s_element **ptr, size_t len, const str goto free_out; } - json_buf = safe_malloc(gen_len + 1); + json_buf = smart_safe_malloc(gen_len, 1, 1); (void)memcpy(json_buf, gen_buf, gen_len); json_buf[gen_len] = '\\0'; -- 2.34.1