diff --git a/src/lxc/arguments.h b/src/lxc/arguments.h index 78337485d..8ace559fb 100644 --- a/src/lxc/arguments.h +++ b/src/lxc/arguments.h @@ -61,7 +61,7 @@ struct lxc_arguments { const char *share_ns[32]; // size must be greater than LXC_NS_MAX /* for lxc-console */ - int ttynum; + unsigned int ttynum; char escape; /* for lxc-wait */ diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 6bf41013c..d5ea3c07b 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2504,7 +2504,8 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd { char veth1buf[IFNAMSIZ], *veth1; char veth2buf[IFNAMSIZ], *veth2; - int bridge_index, err, mtu = 0; + int bridge_index, err; + unsigned int mtu = 0; if (netdev->priv.veth_attr.pair) { veth1 = netdev->priv.veth_attr.pair; @@ -2556,8 +2557,10 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd } if (netdev->mtu) { - mtu = atoi(netdev->mtu); - INFO("Retrieved mtu %d", mtu); + if (lxc_safe_uint(netdev->mtu, &mtu) < 0) + WARN("Failed to parse mtu from."); + else + INFO("Retrieved mtu %d", mtu); } else if (netdev->link) { bridge_index = if_nametoindex(netdev->link); if (bridge_index) { @@ -2706,6 +2709,7 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd char peer[IFNAMSIZ]; int err; static uint16_t vlan_cntr = 0; + unsigned int mtu = 0; if (!netdev->link) { ERROR("no link specified for vlan netdev"); @@ -2735,7 +2739,12 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd DEBUG("instantiated vlan '%s', ifindex is '%d'", " vlan1000", netdev->ifindex); if (netdev->mtu) { - err = lxc_netdev_set_mtu(peer, atoi(netdev->mtu)); + if (lxc_safe_uint(netdev->mtu, &mtu) < 0) { + ERROR("Failed to retrieve mtu from: '%d'/'%s'.", + netdev->ifindex, netdev->name); + return -1; + } + err = lxc_netdev_set_mtu(peer, mtu); if (err) { ERROR("failed to set mtu '%s' for %s : %s", netdev->mtu, peer, strerror(-err)); @@ -4450,8 +4459,10 @@ void suggest_default_idmap(void) p2++; if (!*p2) continue; - uid = atoi(p); - urange = atoi(p2); + if (lxc_safe_uint(p, &uid) < 0) + WARN("Could not parse UID."); + if (lxc_safe_uint(p2, &urange) < 0) + WARN("Could not parse UID range."); } fclose(f); @@ -4479,8 +4490,10 @@ void suggest_default_idmap(void) p2++; if (!*p2) continue; - gid = atoi(p); - grange = atoi(p2); + if (lxc_safe_uint(p, &gid) < 0) + WARN("Could not parse GID."); + if (lxc_safe_uint(p2, &grange) < 0) + WARN("Could not parse GID range."); } fclose(f); diff --git a/src/lxc/conf.h b/src/lxc/conf.h index a0f0c3ebc..ae29d4210 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -62,7 +62,7 @@ enum { struct lxc_inetdev { struct in_addr addr; struct in_addr bcast; - int prefix; + unsigned int prefix; }; struct lxc_route { @@ -80,7 +80,7 @@ struct lxc_inet6dev { struct in6_addr addr; struct in6_addr mcast; struct in6_addr acast; - int prefix; + unsigned int prefix; }; struct lxc_route6 { @@ -293,8 +293,8 @@ struct saved_nic { struct lxc_conf { int is_execute; char *fstab; - int tty; - int pts; + unsigned int tty; + unsigned int pts; int reboot; int need_utmp_watch; signed long personality; @@ -317,7 +317,7 @@ struct lxc_conf { struct lxc_list hooks[NUM_LXC_HOOKS]; char *lsm_aa_profile; - int lsm_aa_allow_incomplete; + unsigned int lsm_aa_allow_incomplete; char *lsm_se_context; int tmp_umount_proc; char *seccomp; // filename with the seccomp rules @@ -325,11 +325,11 @@ struct lxc_conf { scmp_filter_ctx seccomp_ctx; #endif int maincmd_fd; - int autodev; // if 1, mount and fill a /dev at start + unsigned int autodev; // if 1, mount and fill a /dev at start int haltsignal; // signal used to halt container int rebootsignal; // signal used to reboot container int stopsignal; // signal used to hard stop container - int kmsg; // if 1, create /dev/kmsg symlink + unsigned int kmsg; // if 1, create /dev/kmsg symlink char *rcfile; // Copy of the top level rcfile we read // Logfile and logleve can be set in a container config file. @@ -343,14 +343,14 @@ struct lxc_conf { int inherit_ns_fd[LXC_NS_MAX]; - int start_auto; - int start_delay; + unsigned int start_auto; + unsigned int start_delay; int start_order; struct lxc_list groups; int nbd_idx; /* unshare the mount namespace in the monitor */ - int monitor_unshare; + unsigned int monitor_unshare; /* set to true when rootfs has been setup */ bool rootfs_setup; @@ -377,7 +377,7 @@ struct lxc_conf { gid_t init_gid; /* indicator if the container will be destroyed on shutdown */ - int ephemeral; + unsigned int ephemeral; /* The facility to pass to syslog. Let's users establish as what type of * program liblxc is supposed to write to the syslog. */ diff --git a/src/lxc/confile.c b/src/lxc/confile.c index 8f370f6cf..d7362caed 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -853,8 +853,12 @@ static int config_network_ipv4(const char *key, const char *value, } /* no prefix specified, determine it from the network class */ - inetdev->prefix = prefix ? atoi(prefix) : - config_ip_prefix(&inetdev->addr); + if (prefix) { + if (lxc_safe_uint(prefix, &inetdev->prefix) < 0) + return -1; + } else { + inetdev->prefix = config_ip_prefix(&inetdev->addr); + } /* if no broadcast address, let compute one from the * prefix and address @@ -952,7 +956,8 @@ static int config_network_ipv6(const char *key, const char *value, if (slash) { *slash = '\0'; netmask = slash + 1; - inet6dev->prefix = atoi(netmask); + if (lxc_safe_uint(netmask, &inet6dev->prefix) < 0) + return -1; } if (!inet_pton(AF_INET6, valdup, &inet6dev->addr)) { @@ -1060,14 +1065,24 @@ static int config_init_cmd(const char *key, const char *value, static int config_init_uid(const char *key, const char *value, struct lxc_conf *lxc_conf) { - lxc_conf->init_uid = atoi(value); + unsigned int init_uid; + + if (lxc_safe_uint(value, &init_uid) < 0) + return -1; + lxc_conf->init_uid = init_uid; + return 0; } static int config_init_gid(const char *key, const char *value, struct lxc_conf *lxc_conf) { - lxc_conf->init_gid = atoi(value); + unsigned int init_gid; + + if (lxc_safe_uint(value, &init_gid) < 0) + return -1; + lxc_conf->init_gid = init_gid; + return 0; } @@ -1127,9 +1142,8 @@ static int config_personality(const char *key, const char *value, static int config_pts(const char *key, const char *value, struct lxc_conf *lxc_conf) { - int maxpts = atoi(value); - - lxc_conf->pts = maxpts; + if (lxc_safe_uint(value, &lxc_conf->pts) < 0) + return -1; return 0; } @@ -1138,15 +1152,20 @@ static int config_start(const char *key, const char *value, struct lxc_conf *lxc_conf) { if(strcmp(key, "lxc.start.auto") == 0) { - lxc_conf->start_auto = atoi(value); + if (lxc_safe_uint(value, &lxc_conf->start_auto) < 0) + return -1; + if (lxc_conf->start_auto > 1) + return -1; return 0; } else if (strcmp(key, "lxc.start.delay") == 0) { - lxc_conf->start_delay = atoi(value); + if (lxc_safe_uint(value, &lxc_conf->start_delay) < 0) + return -1; return 0; } else if (strcmp(key, "lxc.start.order") == 0) { - lxc_conf->start_order = atoi(value); + if (lxc_safe_int(value, &lxc_conf->start_order) < 0) + return -1; return 0; } SYSERROR("Unknown key: %s", key); @@ -1157,7 +1176,8 @@ static int config_monitor(const char *key, const char *value, struct lxc_conf *lxc_conf) { if(strcmp(key, "lxc.monitor.unshare") == 0) { - lxc_conf->monitor_unshare = atoi(value); + if (lxc_safe_uint(value, &lxc_conf->monitor_unshare) < 0) + return -1; return 0; } SYSERROR("Unknown key: %s", key); @@ -1240,9 +1260,8 @@ freak_out: static int config_tty(const char *key, const char *value, struct lxc_conf *lxc_conf) { - int nbtty = atoi(value); - - lxc_conf->tty = nbtty; + if (lxc_safe_uint(value, &lxc_conf->tty) < 0) + return -1; return 0; } @@ -1256,9 +1275,11 @@ static int config_ttydir(const char *key, const char *value, static int config_kmsg(const char *key, const char *value, struct lxc_conf *lxc_conf) { - int v = atoi(value); + if (lxc_safe_uint(value, &lxc_conf->kmsg) < 0) + return -1; - lxc_conf->kmsg = v; + if (lxc_conf->kmsg > 1) + return -1; return 0; } @@ -1272,9 +1293,13 @@ static int config_lsm_aa_profile(const char *key, const char *value, static int config_lsm_aa_incomplete(const char *key, const char *value, struct lxc_conf *lxc_conf) { - int v = atoi(value); + if (lxc_safe_uint(value, &lxc_conf->lsm_aa_allow_incomplete) < 0) + return -1; - lxc_conf->lsm_aa_allow_incomplete = v == 1 ? 1 : 0; + if (lxc_conf->lsm_aa_allow_incomplete > 1) { + ERROR("Wrong value for lxc.lsm_aa_allow_incomplete. Can only be set to 0 or 1"); + return -1; + } return 0; } @@ -1306,10 +1331,12 @@ static int config_loglevel(const char *key, const char *value, if (!value || strlen(value) == 0) return 0; - if (value[0] >= '0' && value[0] <= '9') - newlevel = atoi(value); - else + if (value[0] >= '0' && value[0] <= '9') { + if (lxc_safe_int(value, &newlevel) < 0) + return -1; + } else { newlevel = lxc_log_priority_to_int(value); + } // store these values in the lxc_conf, and then try to set for // actual current logging. lxc_conf->loglevel = newlevel; @@ -1319,9 +1346,13 @@ static int config_loglevel(const char *key, const char *value, static int config_autodev(const char *key, const char *value, struct lxc_conf *lxc_conf) { - int v = atoi(value); + if (lxc_safe_uint(value, &lxc_conf->autodev) < 0) + return -1; - lxc_conf->autodev = v; + if (lxc_conf->autodev > 1) { + ERROR("Wrong value for lxc.autodev. Can only be set to 0 or 1"); + return -1; + } return 0; } @@ -2933,13 +2964,12 @@ bool network_new_hwaddrs(struct lxc_conf *conf) static int config_ephemeral(const char *key, const char *value, struct lxc_conf *lxc_conf) { - int v = atoi(value); + if (lxc_safe_uint(value, &lxc_conf->ephemeral) < 0) + return -1; - if (v != 0 && v != 1) { + if (lxc_conf->ephemeral > 1) { ERROR("Wrong value for lxc.ephemeral. Can only be set to 0 or 1"); return -1; - } else { - lxc_conf->ephemeral = v; } return 0; @@ -2951,7 +2981,7 @@ static int config_syslog(const char *key, const char *value, int facility; facility = lxc_syslog_priority_to_int(value); if (facility == -EINVAL) { - ERROR("Wrong value for lxc.syslog"); + ERROR("Wrong value for lxc.syslog."); return -1; } @@ -2962,12 +2992,16 @@ static int config_syslog(const char *key, const char *value, static int config_no_new_privs(const char *key, const char *value, struct lxc_conf *lxc_conf) { - int v = atoi(value); + unsigned int v; - if (v != 0 && v != 1) { + if (lxc_safe_uint(value, &v) < 0) + return -1; + + if (v > 1) { ERROR("Wrong value for lxc.no_new_privs. Can only be set to 0 or 1"); return -1; } + lxc_conf->no_new_privs = v ? true : false; return 0; diff --git a/src/lxc/lxc_monitord.c b/src/lxc/lxc_monitord.c index c317cbe78..61c8411fb 100644 --- a/src/lxc/lxc_monitord.c +++ b/src/lxc/lxc_monitord.c @@ -362,14 +362,15 @@ int main(int argc, char *argv[]) ret = snprintf(logpath, sizeof(logpath), "%s/lxc-monitord.log", (strcmp(LXCPATH, lxcpath) ? lxcpath : LOGPATH ) ); if (ret < 0 || ret >= sizeof(logpath)) - return EXIT_FAILURE; + exit(EXIT_FAILURE); ret = lxc_log_init(NULL, logpath, "NOTICE", "lxc-monitord", 0, lxcpath); if (ret) INFO("Failed to open log file %s, log will be lost", lxcpath); lxc_log_options_no_override(); - pipefd = atoi(argv[2]); + if (lxc_safe_int(argv[2], &pipefd) < 0) + exit(EXIT_FAILURE); if (sigfillset(&mask) || sigdelset(&mask, SIGILL) || @@ -378,7 +379,7 @@ int main(int argc, char *argv[]) sigdelset(&mask, SIGTERM) || sigprocmask(SIG_BLOCK, &mask, NULL)) { SYSERROR("failed to set signal mask"); - return 1; + exit(EXIT_FAILURE); } signal(SIGILL, lxc_monitord_sig_handler); @@ -428,7 +429,5 @@ int main(int argc, char *argv[]) ret = EXIT_SUCCESS; NOTICE("monitor exiting"); out: - if (ret == 0) - return 0; - return 1; + exit(ret); } diff --git a/src/lxc/start.c b/src/lxc/start.c index f36653dff..71206e036 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -223,7 +223,10 @@ restart: if (!strcmp(direntp->d_name, "..")) continue; - fd = atoi(direntp->d_name); + if (lxc_safe_int(direntp->d_name, &fd) < 0) { + INFO("Could not parse file descriptor for: %s", direntp->d_name); + continue; + } if (fd == fddir || fd == lxc_log_fd || fd == fd_to_ignore) continue; diff --git a/src/lxc/tools/lxc_autostart.c b/src/lxc/tools/lxc_autostart.c index 267cb6c61..a24dd7cdd 100644 --- a/src/lxc/tools/lxc_autostart.c +++ b/src/lxc/tools/lxc_autostart.c @@ -26,6 +26,7 @@ #include "arguments.h" #include "list.h" #include "log.h" +#include "utils.h" lxc_log_define(lxc_autostart_ui, lxc); static struct lxc_list *accumulate_list(char *input, char *delimiter, struct lxc_list *str_list); @@ -35,14 +36,31 @@ struct lxc_list *cmd_groups_list = NULL; static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { - case 'k': args->hardstop = 1; break; - case 'L': args->list = 1; break; - case 'r': args->reboot = 1; break; - case 's': args->shutdown = 1; break; - case 'a': args->all = 1; break; - case 'A': args->ignore_auto = 1; break; - case 'g': cmd_groups_list = accumulate_list( arg, ",", cmd_groups_list); break; - case 't': args->timeout = atoi(arg); break; + case 'k': + args->hardstop = 1; + break; + case 'L': + args->list = 1; + break; + case 'r': + args->reboot = 1; + break; + case 's': + args->shutdown = 1; + break; + case 'a': + args->all = 1; + break; + case 'A': + args->ignore_auto = 1; + break; + case 'g': + cmd_groups_list = accumulate_list(arg, ",", cmd_groups_list); + break; + case 't': + if (lxc_safe_long(arg, &args->timeout) < 0) + return -1; + break; } return 0; } @@ -290,7 +308,9 @@ static int get_config_integer(struct lxc_container *c, char *key) { return 0; } - ret = atoi(value); + if (lxc_safe_int(value, &ret) < 0) + DEBUG("Could not parse config item."); + free(value); return ret; diff --git a/src/lxc/tools/lxc_console.c b/src/lxc/tools/lxc_console.c index 5d8dd4d0b..88a24bec3 100644 --- a/src/lxc/tools/lxc_console.c +++ b/src/lxc/tools/lxc_console.c @@ -22,29 +22,29 @@ */ #define _GNU_SOURCE -#include -#undef _GNU_SOURCE -#include #include -#include #include -#include -#include #include #include -#include -#include -#include +#include +#include +#include +#include +#include #include +#include +#include +#include #include -#include "error.h" -#include "lxc.h" -#include "log.h" -#include "mainloop.h" #include "arguments.h" #include "commands.h" +#include "error.h" +#include "log.h" +#include "lxc.h" +#include "mainloop.h" +#include "utils.h" lxc_log_define(lxc_console_ui, lxc); @@ -58,8 +58,13 @@ static char etoc(const char *expr) static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { - case 't': args->ttynum = atoi(arg); break; - case 'e': args->escape = etoc(arg); break; + case 't': + if (lxc_safe_uint(arg, &args->ttynum) < 0) + return -1; + break; + case 'e': + args->escape = etoc(arg); + break; } return 0; } diff --git a/src/lxc/tools/lxc_execute.c b/src/lxc/tools/lxc_execute.c index 13fa79952..fae2dca0a 100644 --- a/src/lxc/tools/lxc_execute.c +++ b/src/lxc/tools/lxc_execute.c @@ -58,10 +58,19 @@ static int my_checker(const struct lxc_arguments* args) static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { - case 'f': args->rcfile = arg; break; - case 's': return lxc_config_define_add(&defines, arg); break; - case 'u': args->uid = atoi(arg); break; - case 'g': args->gid = atoi(arg); + case 'f': + args->rcfile = arg; + break; + case 's': + return lxc_config_define_add(&defines, arg); + break; + case 'u': + if (lxc_safe_uint(arg, &args->uid) < 0) + return -1; + break; + case 'g': + if (lxc_safe_uint(arg, &args->gid) < 0) + return -1; } return 0; } diff --git a/src/lxc/tools/lxc_ls.c b/src/lxc/tools/lxc_ls.c index 5e2cb4af1..b5ddeefdb 100644 --- a/src/lxc/tools/lxc_ls.c +++ b/src/lxc/tools/lxc_ls.c @@ -459,8 +459,14 @@ static int ls_get(struct ls **m, size_t *size, const struct lxc_arguments *args, goto put_and_next; tmp = ls_get_config_item(c, "lxc.start.auto", running); - if (tmp) - l->autostart = atoi(tmp); + if (tmp) { + unsigned int astart = 0; + if (lxc_safe_uint(tmp, &astart) < 0) + WARN("Could not parse value for 'lxc.start.auto'."); + if (astart > 1) + DEBUG("Wrong value for 'lxc.start.auto = %d'.", astart); + l->autostart = astart == 1 ? true : false; + } free(tmp); if (running) { diff --git a/src/lxc/tools/lxc_stop.c b/src/lxc/tools/lxc_stop.c index d87ed16e1..64b742d98 100644 --- a/src/lxc/tools/lxc_stop.c +++ b/src/lxc/tools/lxc_stop.c @@ -38,15 +38,28 @@ lxc_log_define(lxc_stop_ui, lxc); -static int my_parser(struct lxc_arguments* args, int c, char* arg) +static int my_parser(struct lxc_arguments *args, int c, char *arg) { switch (c) { - case 'r': args->reboot = 1; break; - case 'W': args->nowait = 1; break; - case 't': args->timeout = atoi(arg); break; - case 'k': args->hardstop = 1; break; - case OPT_NO_LOCK: args->nolock = 1; break; - case OPT_NO_KILL: args->nokill = 1; break; + case 'r': + args->reboot = 1; + break; + case 'W': + args->nowait = 1; + break; + case 't': + if (lxc_safe_long(arg, &args->timeout) < 0) + return -1; + break; + case 'k': + args->hardstop = 1; + break; + case OPT_NO_LOCK: + args->nolock = 1; + break; + case OPT_NO_KILL: + args->nokill = 1; + break; } return 0; } @@ -155,17 +168,14 @@ int main(int argc, char *argv[]) /* Set default timeout */ if (my_args.timeout == -2) { - if (my_args.hardstop) { + if (my_args.hardstop) my_args.timeout = 0; - } - else { + else my_args.timeout = 60; - } } - if (my_args.nowait) { + if (my_args.nowait) my_args.timeout = 0; - } /* some checks */ if (!my_args.hardstop && my_args.timeout < -1) { diff --git a/src/lxc/tools/lxc_top.c b/src/lxc/tools/lxc_top.c index faeab3361..d8e7247ad 100644 --- a/src/lxc/tools/lxc_top.c +++ b/src/lxc/tools/lxc_top.c @@ -74,9 +74,16 @@ static int ct_alloc_cnt = 0; static int my_parser(struct lxc_arguments* args, int c, char* arg) { switch (c) { - case 'd': delay = atoi(arg); break; - case 's': sort_by = arg[0]; break; - case 'r': sort_reverse = 1; break; + case 'd': + if (lxc_safe_int(arg, &delay) < 0) + return -1; + break; + case 's': + sort_by = arg[0]; + break; + case 'r': + sort_reverse = 1; + break; } return 0; } diff --git a/src/lxc/utils.c b/src/lxc/utils.c index 9198340f6..200f5cdaf 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -1766,7 +1766,7 @@ int mount_proc_if_needed(const char *rootfs) { char path[MAXPATHLEN]; char link[20]; - int linklen, ret; + int link_to_pid, linklen, ret; int mypid; ret = snprintf(path, MAXPATHLEN, "%s/proc/self", rootfs); @@ -1785,7 +1785,9 @@ int mount_proc_if_needed(const char *rootfs) } if (linklen < 0) /* /proc not mounted */ goto domount; - if (atoi(link) != mypid) { + if (lxc_safe_int(link, &link_to_pid) < 0) + return -1; + if (link_to_pid != mypid) { /* wrong /procs mounted */ umount2(path, MNT_DETACH); /* ignore failure */ goto domount; @@ -1988,3 +1990,63 @@ int lxc_preserve_ns(const int pid, const char *ns) return open(path, O_RDONLY | O_CLOEXEC); } + +int lxc_safe_uint(const char *numstr, unsigned int *converted) +{ + char *err = NULL; + unsigned long int uli; + + errno = 0; + uli = strtoul(numstr, &err, 0); + if (errno > 0) + return -errno; + + if (!err || err == numstr || *err != '\0') + return -EINVAL; + + if (uli > UINT_MAX) + return -ERANGE; + + *converted = (unsigned int)uli; + return 0; +} + +int lxc_safe_int(const char *numstr, int *converted) +{ + char *err = NULL; + signed long int sli; + + errno = 0; + sli = strtol(numstr, &err, 0); + if (errno > 0) + return -errno; + + if (!err || err == numstr || *err != '\0') + return -EINVAL; + + if (sli > INT_MAX) + return -ERANGE; + + *converted = (int)sli; + return 0; +} + +int lxc_safe_long(const char *numstr, long int *converted) +{ + char *err = NULL; + signed long int sli; + + errno = 0; + sli = strtol(numstr, &err, 0); + if (errno > 0) + return -errno; + + if (!err || err == numstr || *err != '\0') + return -EINVAL; + + if (sli > LONG_MAX) + return -ERANGE; + + *converted = sli; + return 0; +} diff --git a/src/lxc/utils.h b/src/lxc/utils.h index 9b92daf3d..0d63bb699 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -316,4 +316,10 @@ int lxc_preserve_ns(const int pid, const char *ns); /* Check whether a signal is blocked by a process. */ bool task_blocking_signal(pid_t pid, int signal); + +/* Helper functions to parse numbers. */ +int lxc_safe_uint(const char *numstr, unsigned int *converted); +int lxc_safe_int(const char *numstr, int *converted); +int lxc_safe_long(const char *numstr, long int *converted); + #endif /* __LXC_UTILS_H */ diff --git a/src/tests/lxc-test-utils.c b/src/tests/lxc-test-utils.c index 081ed4b9e..ecbbca10f 100644 --- a/src/tests/lxc-test-utils.c +++ b/src/tests/lxc-test-utils.c @@ -22,8 +22,11 @@ */ #define _GNU_SOURCE +#define __STDC_FORMAT_MACROS #include #include +#include +#include #include #include #include @@ -222,6 +225,100 @@ non_test_error: exit(fret); } +void test_lxc_safe_uint(void) +{ + int ret; + unsigned int n; + size_t len = /* 2^64 = 21 - 1 */ 21; + char uint_max[len]; + + ret = snprintf(uint_max, len, "%lu", (unsigned long)UINT_MAX + 1); + if (ret < 0 || (size_t)ret >= len) { + lxc_error("%s\n", "Failed to create string via snprintf()."); + exit(EXIT_FAILURE); + } + + lxc_test_assert_abort((0 == lxc_safe_uint("1234345", &n)) && n == 1234345); + lxc_test_assert_abort((0 == lxc_safe_uint(" 345", &n)) && n == 345); + lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" g345", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" 3g45", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" 345g", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g345", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_uint("3g45", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_uint("345g", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g345 ", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_uint("3g45 ", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_uint("345g ", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" g345", &n))); + lxc_test_assert_abort((-ERANGE == lxc_safe_uint(uint_max, &n))); +} + +void test_lxc_safe_int(void) +{ + int ret; + signed int n; + size_t len = /* 2^64 = 21 - 1 */ 21; + char int_max[len]; + + ret = snprintf(int_max, len, "%ld", (signed long)INT_MAX + 1); + if (ret < 0 || (size_t)ret >= len) { + lxc_error("%s\n", "Failed to create string via snprintf()."); + exit(EXIT_FAILURE); + } + + lxc_test_assert_abort((0 == lxc_safe_int("1234345", &n)) && n == 1234345); + lxc_test_assert_abort((0 == lxc_safe_int(" 345", &n)) && n == 345); + lxc_test_assert_abort((0 == lxc_safe_int("-1234345", &n)) && n == -1234345); + lxc_test_assert_abort((0 == lxc_safe_int(" -345", &n)) && n == -345); + lxc_test_assert_abort((-EINVAL == lxc_safe_int(" g345", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_int(" 3g45", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_int(" 345g", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_int("g345", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_int("3g45", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_int("345g", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_int("g345 ", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_int("3g45 ", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_int("345g ", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_int("g", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_int(" g345", &n))); + lxc_test_assert_abort((-ERANGE == lxc_safe_int(int_max, &n))); +} + +void test_lxc_safe_long(void) +{ + int ret; + signed long int n; + size_t len = /* 2^64 = 21 - 1 */ 21; + char long_max[len]; + + ret = snprintf(long_max, len, "%lld", LLONG_MAX); + if (ret < 0 || (size_t)ret >= len) { + lxc_error("%s\n", "Failed to create string via snprintf()."); + exit(EXIT_FAILURE); + } + + lxc_test_assert_abort((0 == lxc_safe_long("1234345", &n)) && n == 1234345); + lxc_test_assert_abort((0 == lxc_safe_long(" 345", &n)) && n == 345); + lxc_test_assert_abort((0 == lxc_safe_long("-1234345", &n)) && n == -1234345); + lxc_test_assert_abort((0 == lxc_safe_long(" -345", &n)) && n == -345); + lxc_test_assert_abort((-EINVAL == lxc_safe_long(" g345", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_long(" 3g45", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_long(" 345g", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_long("g345", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_long("3g45", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_long("345g", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_long("g345 ", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_long("3g45 ", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_long("345g ", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_long("g", &n))); + lxc_test_assert_abort((-EINVAL == lxc_safe_long(" g345", &n))); + if (LONG_MAX != LLONG_MAX) + lxc_test_assert_abort((-ERANGE == lxc_safe_long(long_max, &n))); + else + lxc_test_assert_abort((0 == lxc_safe_long(long_max, &n)) && n == LONG_MAX); +} + void test_lxc_string_replace(void) { char *s; @@ -280,6 +377,9 @@ int main(int argc, char *argv[]) test_lxc_string_in_array(); test_lxc_deslashify(); test_detect_ramfs_rootfs(); + test_lxc_safe_uint(); + test_lxc_safe_int(); + test_lxc_safe_long(); exit(EXIT_SUCCESS); }