lcr/0007-Fix-empty-pointer-and-overflow.patch
openeuler-sync-bot b213050449 !250 [sync] PR-246: Fix potential log error, empty pointer reference and overflow.
* Fix potential log error, empty pointer reference and overflow.
2023-09-12 06:09:34 +00:00

1002 lines
33 KiB
Diff

From 2df5066a9741e9534d13bc422dad69bb6a2c12ce Mon Sep 17 00:00:00 2001
From: jikai <jikai11@huawei.com>
Date: Mon, 28 Aug 2023 12:59:08 +0000
Subject: [PATCH 07/11] Fix empty pointer and overflow
Signed-off-by: jikai <jikai11@huawei.com>
---
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<const char *>(data), size);
std::vector<std::string> 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.33.0