diff options
| author | Garrett D'Amore <garrett@damore.org> | 2017-08-25 11:11:35 -0700 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2017-08-28 11:39:03 -0700 |
| commit | 601c64ec4f2b8a41fba59d31a987090feeb69e84 (patch) | |
| tree | 985ec57b3e238b4eed9b42ddaa4736b949df8c6f | |
| parent | 595da8102f3e34e95dad351bc55cd45421616723 (diff) | |
| download | nng-601c64ec4f2b8a41fba59d31a987090feeb69e84.tar.gz nng-601c64ec4f2b8a41fba59d31a987090feeb69e84.tar.bz2 nng-601c64ec4f2b8a41fba59d31a987090feeb69e84.zip | |
Introduce utility safe string handling functions.
We have our versions of strdup, strlcat, and strlcpy.
This means we can avoid using snprintf() in many cases
(saving cycles), and we can get safer checks. We use
the platform supplied versions of these if they exist
(wrapping with nni_xxx versions.)
| -rw-r--r-- | CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/endpt.c | 3 | ||||
| -rw-r--r-- | src/core/list.c | 2 | ||||
| -rw-r--r-- | src/core/nng_impl.h | 1 | ||||
| -rw-r--r-- | src/core/options.c | 6 | ||||
| -rw-r--r-- | src/core/strs.c | 98 | ||||
| -rw-r--r-- | src/core/strs.h | 21 | ||||
| -rw-r--r-- | src/core/transport.c | 11 | ||||
| -rw-r--r-- | src/platform/posix/posix_ipc.c | 7 | ||||
| -rw-r--r-- | src/platform/posix/posix_sockaddr.c | 5 | ||||
| -rw-r--r-- | src/transport/ipc/ipc.c | 20 | ||||
| -rw-r--r-- | src/transport/tcp/tcp.c | 9 |
13 files changed, 169 insertions, 20 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d7d05c56..87320843 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -239,6 +239,10 @@ else () nng_check_struct_member(msghdr msg_control sys/socket.h NNG_HAVE_MSG_CONTROL) endif () +nng_check_sym (strdup string.h NNG_HAVE_STRDUP) +nng_check_sym (strlcat string.h NNG_HAVE_STRLCAT) +nng_check_sym (strlcpy string.h NNG_HAVE_STRLCPY) + add_subdirectory (src) if (NNG_TESTS) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1510d633..1d616e95 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -66,6 +66,8 @@ set (NNG_SOURCES core/random.h core/socket.c core/socket.h + core/strs.c + core/strs.h core/taskq.c core/taskq.h core/thread.c diff --git a/src/core/endpt.c b/src/core/endpt.c index f6aaf629..9dc33867 100644 --- a/src/core/endpt.c +++ b/src/core/endpt.c @@ -146,8 +146,7 @@ nni_ep_create(nni_ep **epp, nni_sock *s, const char *addr, int mode) // dereference on hot paths. ep->ep_ops = *tran->tran_ep; - // Could safely use strcpy here, but this avoids discussion. - (void) snprintf(ep->ep_addr, sizeof(ep->ep_addr), "%s", addr); + (void) nni_strlcpy(ep->ep_addr, addr, sizeof(ep->ep_addr)); NNI_LIST_NODE_INIT(&ep->ep_node); diff --git a/src/core/list.c b/src/core/list.c index 97fe5c30..8b26b64a 100644 --- a/src/core/list.c +++ b/src/core/list.c @@ -1,5 +1,5 @@ // -// Copyright 2017up Garrett D'Amore <garrett@damore.org> +// Copyright 2017 Garrett D'Amore <garrett@damore.org> // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this diff --git a/src/core/nng_impl.h b/src/core/nng_impl.h index 8510dfb5..905411d7 100644 --- a/src/core/nng_impl.h +++ b/src/core/nng_impl.h @@ -38,6 +38,7 @@ #include "core/panic.h" #include "core/protocol.h" #include "core/random.h" +#include "core/strs.h" #include "core/taskq.h" #include "core/thread.h" #include "core/timer.h" diff --git a/src/core/options.c b/src/core/options.c index 03002d6c..4027564c 100644 --- a/src/core/options.c +++ b/src/core/options.c @@ -275,13 +275,11 @@ nni_option_set_id(const char *name, int id) nni_mtx_unlock(&nni_option_lk); return (NNG_ENOMEM); } - len = strlen(name) + 1; - if ((opt->o_name = nni_alloc(len)) == NULL) { + if ((opt->o_name = nni_strdup(name)) == NULL) { nni_mtx_unlock(&nni_option_lk); NNI_FREE_STRUCT(opt); return (NNG_ENOMEM); } - (void) snprintf(opt->o_name, len, "%s", name); if (id < 0) { id = nni_option_nextid++; } @@ -347,7 +345,7 @@ nni_option_sys_fini(void) nni_option *opt; while ((opt = nni_list_first(&nni_options)) != NULL) { nni_list_remove(&nni_options, opt); - nni_free(opt->o_name, strlen(opt->o_name) + 1); + nni_strfree(opt->o_name); NNI_FREE_STRUCT(opt); } } diff --git a/src/core/strs.c b/src/core/strs.c new file mode 100644 index 00000000..7f236236 --- /dev/null +++ b/src/core/strs.c @@ -0,0 +1,98 @@ +// +// Copyright 2017 Garrett D'Amore <garrett@damore.org> +// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#include <stdlib.h> +#include <string.h> + +#include "core/nng_impl.h" + +// This file contains implementation of utility functions that are not +// part of standard C99. (C11 has added some things here, but we cannot +// count on them.) + +char * +nni_strdup(const char *src) +{ +#ifdef NNG_HAVE_STRDUP + return (strdup(src)); +#else + char * dst; + size_t len = strlen(src); + + if ((dst = nni_alloc(len)) != NULL) { + memcpy(dst, src, len); + } + return (dst); +#endif +} + +void +nni_strfree(char *s) +{ + if (s != NULL) { +#ifdef NNG_HAVE_STRDUP + free(s); +#else + nni_free(s, strlen(s) + 1); +#endif + } +} + +size_t +nni_strlcpy(char *dst, const char *src, size_t len) +{ +#ifdef NNG_HAVE_STRLCPY + return (strlcpy(dst, src, len)); +#else + size_t n; + char c; + + n = 0; + do { + c = *src++; + n++; + if (n < len) { + *dst++ = c; + } else if (n == len) { + *dst = '\0'; + } + } while (c); + return (n - 1); +#endif +} + +size_t +nni_strlcat(char *dst, const char *src, size_t len) +{ +#ifdef NNG_HAVE_STRLCAT + return (strlcat(dst, src, len)); +#else + size_t n; + char c; + + n = 0; + while ((*dst != '\0') && (n < len)) { + n++; + dst++; + } + + do { + c = *src++; + n++; + if (n < len) { + *dst++ = c; + } else if (n == len) { + *dst = '\0'; + } + } while (c); + + return (n - 1); +#endif +} diff --git a/src/core/strs.h b/src/core/strs.h new file mode 100644 index 00000000..741504cd --- /dev/null +++ b/src/core/strs.h @@ -0,0 +1,21 @@ +// +// Copyright 2017 Garrett D'Amore <garrett@damore.org> +// Copyright 2017 Capitar IT Group BV <info@capitar.com> +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#ifndef CORE_STRS_H +#define CORE_STRS_H + +// Safe string functions, in case the platform misses these. + +extern char * nni_strdup(const char *); +extern void nni_strfree(char *); +extern size_t nni_strlcpy(char *, const char *, size_t); +extern size_t nni_strlcat(char *, const char *, size_t); + +#endif // CORE_STRS_H diff --git a/src/core/transport.c b/src/core/transport.c index 3130ae26..eead861b 100644 --- a/src/core/transport.c +++ b/src/core/transport.c @@ -34,6 +34,7 @@ nni_tran_register(const nni_tran *tran) { nni_transport *t; int rv; + size_t sz; // Its entirely possible that we are called before any sockets // are opened. Make sure we are initialized. This has to be @@ -56,12 +57,18 @@ nni_tran_register(const nni_tran *tran) } } if ((t = NNI_ALLOC_STRUCT(t)) == NULL) { + nni_mtx_unlock(&nni_tran_lk); return (NNG_ENOMEM); } t->t_tran = *tran; - (void) snprintf( - t->t_prefix, sizeof(t->t_prefix), "%s://", tran->tran_scheme); + sz = sizeof(t->t_prefix); + if ((nni_strlcpy(t->t_prefix, tran->tran_scheme, sz) >= sz) || + (nni_strlcat(t->t_prefix, "://", sz) >= sz)) { + nni_mtx_unlock(&nni_tran_lk); + NNI_FREE_STRUCT(t); + return (NNG_EINVAL); + } if ((rv = t->t_tran.tran_init()) != 0) { nni_mtx_unlock(&nni_tran_lk); NNI_FREE_STRUCT(t); diff --git a/src/platform/posix/posix_ipc.c b/src/platform/posix/posix_ipc.c index 2daec4ea..f0a9a973 100644 --- a/src/platform/posix/posix_ipc.c +++ b/src/platform/posix/posix_ipc.c @@ -98,9 +98,14 @@ nni_plat_ipc_remove_stale(const char *path) int fd; int rv; struct sockaddr_un sun; + size_t sz; sun.sun_family = AF_UNIX; - snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", path); + sz = sizeof(sun.sun_path); + + if (nni_strlcpy(sun.sun_path, path, sz) >= sz) { + return (NNG_EADDRINVAL); + } if ((fd = socket(AF_UNIX, NNI_STREAM_SOCKTYPE, 0)) < 0) { return (nni_plat_errno(errno)); diff --git a/src/platform/posix/posix_sockaddr.c b/src/platform/posix/posix_sockaddr.c index 21a2b863..ea630b01 100644 --- a/src/platform/posix/posix_sockaddr.c +++ b/src/platform/posix/posix_sockaddr.c @@ -31,6 +31,7 @@ nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na) const nng_sockaddr_in * nsin; const nng_sockaddr_in6 * nsin6; const nng_sockaddr_path *nspath; + size_t sz; switch (na->s_un.s_family) { case NNG_AF_INET: @@ -59,8 +60,8 @@ nni_posix_nn2sockaddr(void *sa, const nni_sockaddr *na) nspath = &na->s_un.s_path; memset(spath, 0, sizeof(*spath)); // Make sure that the path fits! - if (snprintf(spath->sun_path, sizeof(spath->sun_path), "%s", - nspath->sa_path) >= sizeof(spath->sun_path)) { + sz = sizeof(spath->sun_path); + if (nni_strlcpy(spath->sun_path, nspath->sa_path, sz) >= sz) { return (-1); } spath->sun_family = PF_UNIX; diff --git a/src/transport/ipc/ipc.c b/src/transport/ipc/ipc.c index e5e19f36..b2c382fb 100644 --- a/src/transport/ipc/ipc.c +++ b/src/transport/ipc/ipc.c @@ -486,20 +486,29 @@ nni_ipc_ep_init(void **epp, const char *url, nni_sock *sock, int mode) nni_ipc_ep * ep; int rv; nni_sockaddr sa; + size_t sz; - if ((strlen(url) > NNG_MAXADDRLEN - 1) || - (strncmp(url, "ipc://", strlen("ipc://")) != 0)) { + if (strncmp(url, "ipc://", strlen("ipc://")) != 0) { return (NNG_EADDRINVAL); } + url += strlen("ipc://"); + sz = sizeof(sa.s_un.s_path.sa_path); sa.s_un.s_path.sa_family = NNG_AF_IPC; - (void) snprintf(sa.s_un.s_path.sa_path, sizeof(sa.s_un.s_path.sa_path), - "%s", url + strlen("ipc://")); + + if (nni_strlcpy(sa.s_un.s_path.sa_path, url, sz) >= sz) { + return (NNG_EADDRINVAL); + } if ((ep = NNI_ALLOC_STRUCT(ep)) == NULL) { return (NNG_ENOMEM); } - url += strlen("ipc://"); + + if (nni_strlcpy(ep->addr, url, sizeof(ep->addr)) >= sizeof(ep->addr)) { + NNI_FREE_STRUCT(ep); + return (NNG_EADDRINVAL); + } + if ((rv = nni_plat_ipc_ep_init(&ep->iep, &sa, mode)) != 0) { NNI_FREE_STRUCT(ep); return (rv); @@ -509,7 +518,6 @@ nni_ipc_ep_init(void **epp, const char *url, nni_sock *sock, int mode) nni_aio_init(&ep->aio, nni_ipc_ep_cb, ep); ep->proto = nni_sock_proto(sock); - (void) snprintf(ep->addr, sizeof(ep->addr), "%s", url); *epp = ep; return (0); diff --git a/src/transport/tcp/tcp.c b/src/transport/tcp/tcp.c index de1bfa66..f0f07592 100644 --- a/src/transport/tcp/tcp.c +++ b/src/transport/tcp/tcp.c @@ -579,7 +579,9 @@ nni_tcp_ep_init(void **epp, const char *url, nni_sock *sock, int mode) int passive; // Make a copy of the url (to allow for destructive operations) - snprintf(buf, sizeof(buf), "%s", url); + if (nni_strlcpy(buf, url, sizeof(buf)) >= sizeof(buf)) { + return (NNG_EADDRINVAL); + } // Parse the URLs first. rv = nni_tcp_parse_url(buf, &lhost, &lserv, &rhost, &rserv, mode); @@ -620,6 +622,10 @@ nni_tcp_ep_init(void **epp, const char *url, nni_sock *sock, int mode) if ((ep = NNI_ALLOC_STRUCT(ep)) == NULL) { return (NNG_ENOMEM); } + if (nni_strlcpy(ep->addr, url, sizeof(ep->addr)) >= sizeof(ep->addr)) { + NNI_FREE_STRUCT(ep); + return (NNG_EADDRINVAL); + } if ((rv = nni_plat_tcp_ep_init(&ep->tep, &lsa, &rsa, mode)) != 0) { NNI_FREE_STRUCT(ep); @@ -630,7 +636,6 @@ nni_tcp_ep_init(void **epp, const char *url, nni_sock *sock, int mode) nni_aio_init(&ep->aio, nni_tcp_ep_cb, ep); ep->proto = nni_sock_proto(sock); - (void) snprintf(ep->addr, sizeof(ep->addr), "%s", url); *epp = ep; return (0); |
