aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2018-02-05 10:23:35 -0800
committerGarrett D'Amore <garrett@damore.org>2018-02-05 10:23:35 -0800
commit844ce972fed056e1c4e0517e43b814c62d68edce (patch)
treeadfa91e3f7188d268f3d081e80c14f7e8a609a87 /src
parentb893f8ff1f96dde567fa6a75f4b15bf69e53d6f5 (diff)
downloadnng-844ce972fed056e1c4e0517e43b814c62d68edce.tar.gz
nng-844ce972fed056e1c4e0517e43b814c62d68edce.tar.bz2
nng-844ce972fed056e1c4e0517e43b814c62d68edce.zip
fixes #228 aio iov should have larger limits (dynamically allocated)
Diffstat (limited to 'src')
-rw-r--r--src/core/aio.c4
-rw-r--r--src/core/aio.h4
-rw-r--r--src/nng.c18
-rw-r--r--src/nng.h2
-rw-r--r--src/platform/posix/posix_pipedesc.c58
-rw-r--r--src/platform/posix/posix_udp.c25
-rw-r--r--src/platform/windows/win_ipc.c4
-rw-r--r--src/platform/windows/win_tcp.c8
-rw-r--r--src/platform/windows/win_udp.c25
-rw-r--r--src/supplemental/http/http_conn.c6
-rw-r--r--src/supplemental/tls/mbedtls/tls.c8
11 files changed, 121 insertions, 41 deletions
diff --git a/src/core/aio.c b/src/core/aio.c
index 341b218e..ee1ddf2a 100644
--- a/src/core/aio.c
+++ b/src/core/aio.c
@@ -147,7 +147,7 @@ nni_aio_fini(nni_aio *aio)
}
int
-nni_aio_set_iov(nni_aio *aio, int niov, const nni_iov *iov)
+nni_aio_set_iov(nni_aio *aio, unsigned niov, const nni_iov *iov)
{
if ((niov > NNI_NUM_ELEMENTS(aio->a_iovinl)) &&
(niov > aio->a_niovalloc)) {
@@ -584,7 +584,7 @@ nni_aio_set_prov_extra(nni_aio *aio, unsigned index, void *data)
}
void
-nni_aio_get_iov(nni_aio *aio, int *niovp, nni_iov **iovp)
+nni_aio_get_iov(nni_aio *aio, unsigned *niovp, nni_iov **iovp)
{
*niovp = aio->a_niov;
*iovp = aio->a_iov;
diff --git a/src/core/aio.h b/src/core/aio.h
index 34f4a56b..b17c8e97 100644
--- a/src/core/aio.h
+++ b/src/core/aio.h
@@ -147,10 +147,10 @@ extern size_t nni_aio_iov_advance(nni_aio *, size_t);
// nni_aio_iov_count returns the number of bytes referenced by the aio's iov.
extern size_t nni_aio_iov_count(nni_aio *);
-extern int nni_aio_set_iov(nni_aio *, int, const nni_iov *);
+extern int nni_aio_set_iov(nni_aio *, unsigned, const nni_iov *);
extern void nni_aio_set_timeout(nni_aio *, nng_duration);
-extern void nni_aio_get_iov(nni_aio *, int *, nni_iov **);
+extern void nni_aio_get_iov(nni_aio *, unsigned *, nni_iov **);
extern void nni_aio_normalize_timeout(nni_aio *, nng_duration);
extern void nni_aio_bump_count(nni_aio *, size_t);
diff --git a/src/nng.c b/src/nng.c
index 92d19d87..6f710993 100644
--- a/src/nng.c
+++ b/src/nng.c
@@ -1086,8 +1086,22 @@ nng_aio_set_timeout(nng_aio *aio, nni_duration when)
}
int
-nng_aio_set_iov(nng_aio *aio, int niov, nng_iov *iov)
-{
+nng_aio_set_iov(nng_aio *aio, unsigned niov, const nng_iov *iov)
+{
+// We limit the niov to prevent user insanity. This is required
+// to avoid stack allocations that might smash the stack. The
+// assumption is that we can always put at least 1kB on the stack --
+// our nng_iov structures are 16B. Systems without stack allocation
+// get a smaller limit, because we use an automatic variable.
+#if defined(NNG_HAVE_ALLOCA) || defined(_WIN32)
+ if (niov > 64) {
+ return (NNG_EINVAL);
+ }
+#else
+ if (niov > 16) {
+ return (NNG_EINVAL);
+ }
+#endif
return (nni_aio_set_iov(aio, niov, iov));
}
diff --git a/src/nng.h b/src/nng.h
index a5b3346a..049651c1 100644
--- a/src/nng.h
+++ b/src/nng.h
@@ -334,7 +334,7 @@ NNG_DECL void nng_aio_set_timeout(nng_aio *, nng_duration);
// itself is copied. Data members (the memory regions referenced) *may* be
// copied as well, depending on the operation. This operation is guaranteed
// to succeed if n <= 4, otherwise it may fail due to NNG_ENOMEM.
-NNG_DECL int nng_aio_set_iov(nng_aio *, int, nng_iov *);
+NNG_DECL int nng_aio_set_iov(nng_aio *, unsigned, const nng_iov *);
// Message API.
NNG_DECL int nng_msg_alloc(nng_msg **, size_t);
diff --git a/src/platform/posix/posix_pipedesc.c b/src/platform/posix/posix_pipedesc.c
index 23d69e51..f387c60c 100644
--- a/src/platform/posix/posix_pipedesc.c
+++ b/src/platform/posix/posix_pipedesc.c
@@ -69,14 +69,32 @@ nni_posix_pipedesc_dowrite(nni_posix_pipedesc *pd)
nni_aio *aio;
while ((aio = nni_list_first(&pd->writeq)) != NULL) {
- int i;
- int n;
- struct iovec iovec[4];
- int niov;
- int naiov;
- nni_iov * aiov;
+ unsigned i;
+ int n;
+ int niov;
+ unsigned naiov;
+ nni_iov *aiov;
+#ifdef NNG_HAVE_ALLOCA
+ struct iovec *iovec;
+#else
+ struct iovec iovec[16];
+#endif
nni_aio_get_iov(aio, &naiov, &aiov);
+
+#ifdef NNG_HAVE_ALLOCA
+ if (naiov > 64) {
+ nni_posix_pipedesc_finish(aio, NNG_EINVAL);
+ continue;
+ }
+ iovec = alloca(naiov * sizeof(*iovec));
+#else
+ if (naiov > NNI_NUM_ELEMENTS(iovec)) {
+ nni_posix_pipedesc_finish(aio, NNG_EINVAL);
+ continue;
+ }
+#endif
+
for (niov = 0, i = 0; i < naiov; i++) {
if (aiov[i].iov_len > 0) {
iovec[niov].iov_len = aiov[i].iov_len;
@@ -112,14 +130,30 @@ nni_posix_pipedesc_doread(nni_posix_pipedesc *pd)
nni_aio *aio;
while ((aio = nni_list_first(&pd->readq)) != NULL) {
- int i;
- int n;
- struct iovec iovec[4];
- int niov;
- int naiov;
- nni_iov * aiov;
+ unsigned i;
+ int n;
+ int niov;
+ unsigned naiov;
+ nni_iov *aiov;
+#ifdef NNG_HAVE_ALLOCA
+ struct iovec *iovec;
+#else
+ struct iovec iovec[16];
+#endif
nni_aio_get_iov(aio, &naiov, &aiov);
+#ifdef NNG_HAVE_ALLOCA
+ if (naiov > 64) {
+ nni_posix_pipedesc_finish(aio, NNG_EINVAL);
+ continue;
+ }
+ iovec = alloca(naiov * sizeof(*iovec));
+#else
+ if (naiov > NNI_NUM_ELEMENTS(iovec)) {
+ nni_posix_pipedesc_finish(aio, NNG_EINVAL);
+ continue;
+ }
+#endif
for (niov = 0, i = 0; i < naiov; i++) {
if (aiov[i].iov_len != 0) {
iovec[niov].iov_len = aiov[i].iov_len;
diff --git a/src/platform/posix/posix_udp.c b/src/platform/posix/posix_udp.c
index e01f6883..cd7b0561 100644
--- a/src/platform/posix/posix_udp.c
+++ b/src/platform/posix/posix_udp.c
@@ -63,7 +63,7 @@ nni_posix_udp_dorecv(nni_plat_udp *udp)
// While we're able to recv, do so.
while ((aio = nni_list_first(q)) != NULL) {
struct iovec iov[4];
- int niov;
+ unsigned niov;
nni_iov * aiov;
struct sockaddr_storage ss;
nng_sockaddr * sa;
@@ -73,7 +73,7 @@ nni_posix_udp_dorecv(nni_plat_udp *udp)
nni_aio_get_iov(aio, &niov, &aiov);
- for (int i = 0; i < niov; i++) {
+ for (unsigned i = 0; i < niov; i++) {
iov[i].iov_base = aiov[i].iov_buf;
iov[i].iov_len = aiov[i].iov_len;
}
@@ -123,13 +123,28 @@ nni_posix_udp_dosend(nni_plat_udp *udp)
rv = NNG_EADDRINVAL;
} else {
struct msghdr hdr;
- struct iovec iov[4];
- int niov;
+ unsigned niov;
nni_iov * aiov;
+#ifdef NNG_HAVE_ALLOCA
+ struct iovec *iov;
+#else
+ struct iovec iov[16];
+#endif
nni_aio_get_iov(aio, &niov, &aiov);
+#ifdef NNG_HAVE_ALLOCA
+ if (niov > 64) {
+ rv = NNG_EINVAL;
+ } else {
+ iov = alloca(niov * sizeof(*iov));
+ }
+#else
+ if (niov > NNI_NUM_ELEMENTS(iov)) {
+ rv = NNG_EINVAL;
+ }
+#endif
- for (int i = 0; i < niov; i++) {
+ for (unsigned i = 0; i < niov; i++) {
iov[i].iov_base = aiov[i].iov_buf;
iov[i].iov_len = aiov[i].iov_len;
}
diff --git a/src/platform/windows/win_ipc.c b/src/platform/windows/win_ipc.c
index 022a18ea..76180d23 100644
--- a/src/platform/windows/win_ipc.c
+++ b/src/platform/windows/win_ipc.c
@@ -59,8 +59,8 @@ nni_win_ipc_pipe_start(nni_win_event *evt, nni_aio *aio)
BOOL ok;
int rv;
nni_plat_ipc_pipe *pipe = evt->ptr;
- int idx;
- int naiov;
+ unsigned idx;
+ unsigned naiov;
nni_iov * aiov;
NNI_ASSERT(aio != NULL);
diff --git a/src/platform/windows/win_tcp.c b/src/platform/windows/win_tcp.c
index c9935719..254cf40b 100644
--- a/src/platform/windows/win_tcp.c
+++ b/src/platform/windows/win_tcp.c
@@ -12,6 +12,7 @@
#ifdef NNG_PLATFORM_WINDOWS
+#include <malloc.h>
#include <stdio.h>
struct nni_plat_tcp_pipe {
@@ -101,15 +102,16 @@ nni_win_tcp_pipe_start(nni_win_event *evt, nni_aio *aio)
{
int rv;
SOCKET s;
- WSABUF iov[4]; // XXX: consider _alloca()
DWORD niov;
DWORD flags;
nni_plat_tcp_pipe *pipe = evt->ptr;
int i;
- int naiov;
+ unsigned naiov;
nni_iov * aiov;
+ WSABUF * iov;
nni_aio_get_iov(aio, &naiov, &aiov);
+ iov = _malloca(naiov * sizeof(*iov));
// Put the AIOs in Windows form.
for (niov = 0, i = 0; i < naiov; i++) {
@@ -121,6 +123,7 @@ nni_win_tcp_pipe_start(nni_win_event *evt, nni_aio *aio)
}
if ((s = pipe->s) == INVALID_SOCKET) {
+ _freea(iov);
evt->status = NNG_ECLOSED;
evt->count = 0;
return (1);
@@ -136,6 +139,7 @@ nni_win_tcp_pipe_start(nni_win_event *evt, nni_aio *aio)
} else {
rv = WSARecv(s, iov, niov, NULL, &flags, &evt->olpd, NULL);
}
+ _freea(iov);
if ((rv == SOCKET_ERROR) &&
((rv = GetLastError()) != ERROR_IO_PENDING)) {
diff --git a/src/platform/windows/win_udp.c b/src/platform/windows/win_udp.c
index ba947719..81aa2c06 100644
--- a/src/platform/windows/win_udp.c
+++ b/src/platform/windows/win_udp.c
@@ -15,6 +15,7 @@
#ifdef NNG_PLATFORM_WINDOWS
+#include <malloc.h>
#include <stdio.h>
struct nni_plat_udp {
@@ -134,11 +135,11 @@ nni_win_udp_start_rx(nni_win_event *evt, nni_aio *aio)
{
int rv;
SOCKET s;
- WSABUF iov[4]; // XXX: consider _alloca
DWORD flags;
nni_plat_udp *u = evt->ptr;
nni_iov * aiov;
- int naiov;
+ unsigned naiov;
+ WSABUF * iov;
if ((s = u->s) == INVALID_SOCKET) {
evt->status = NNG_ECLOSED;
@@ -149,8 +150,13 @@ nni_win_udp_start_rx(nni_win_event *evt, nni_aio *aio)
u->rxsalen = sizeof(SOCKADDR_STORAGE);
nni_aio_get_iov(aio, &naiov, &aiov);
+ // This is a stack allocation- it should always succeed - or
+ // throw an exception if there is not sufficient stack space.
+ // (Turns out it can allocate from the heap, but same semantics.)
+ iov = _malloca(sizeof(*iov) * naiov);
+
// Put the AIOs in Windows form.
- for (int i = 0; i < naiov; i++) {
+ for (unsigned i = 0; i < naiov; i++) {
iov[i].buf = aiov[i].iov_buf;
iov[i].len = (ULONG) aiov[i].iov_len;
}
@@ -164,6 +170,8 @@ nni_win_udp_start_rx(nni_win_event *evt, nni_aio *aio)
rv = WSARecvFrom(u->s, iov, (DWORD) naiov, NULL, &flags,
(struct sockaddr *) &u->rxsa, &u->rxsalen, &evt->olpd, NULL);
+ _freea(iov);
+
if ((rv == SOCKET_ERROR) &&
((rv = GetLastError()) != ERROR_IO_PENDING)) {
// Synchronous failure.
@@ -183,12 +191,12 @@ nni_win_udp_start_tx(nni_win_event *evt, nni_aio *aio)
{
int rv;
SOCKET s;
- WSABUF iov[4];
- int naiov;
+ unsigned naiov;
nni_iov * aiov;
nni_plat_udp *u = evt->ptr;
int salen;
nni_sockaddr *sa;
+ WSABUF * iov;
if ((s = u->s) == INVALID_SOCKET) {
evt->status = NNG_ECLOSED;
@@ -205,8 +213,11 @@ nni_win_udp_start_tx(nni_win_event *evt, nni_aio *aio)
}
nni_aio_get_iov(aio, &naiov, &aiov);
+
+ iov = _malloca(sizeof(*iov) * naiov);
+
// Put the AIOs in Windows form.
- for (int i = 0; i < naiov; i++) {
+ for (unsigned i = 0; i < naiov; i++) {
iov[i].buf = aiov[i].iov_buf;
iov[i].len = (ULONG) aiov[i].iov_len;
}
@@ -219,6 +230,8 @@ nni_win_udp_start_tx(nni_win_event *evt, nni_aio *aio)
rv = WSASendTo(u->s, iov, (DWORD) naiov, NULL, 0,
(struct sockaddr *) &u->txsa, salen, &evt->olpd, NULL);
+ _freea(iov);
+
if ((rv == SOCKET_ERROR) &&
((rv = GetLastError()) != ERROR_IO_PENDING)) {
// Synchronous failure.
diff --git a/src/supplemental/http/http_conn.c b/src/supplemental/http/http_conn.c
index 484d2242..6a72a731 100644
--- a/src/supplemental/http/http_conn.c
+++ b/src/supplemental/http/http_conn.c
@@ -145,7 +145,7 @@ http_rd_buf(nni_http_conn *conn, nni_aio *aio)
int rv;
bool raw = false;
nni_iov *iov;
- int niov;
+ unsigned niov;
rbuf += conn->rd_get;
@@ -274,7 +274,7 @@ http_rd_cb(void *arg)
nni_aio * uaio;
size_t cnt;
int rv;
- int niov;
+ unsigned niov;
nni_iov * iov;
nni_mtx_lock(&conn->mtx);
@@ -377,7 +377,7 @@ http_wr_start(nni_http_conn *conn)
{
nni_aio *aio;
nni_iov *iov;
- int niov;
+ unsigned niov;
if ((aio = conn->wr_uaio) == NULL) {
if ((aio = nni_list_first(&conn->wrq)) == NULL) {
diff --git a/src/supplemental/tls/mbedtls/tls.c b/src/supplemental/tls/mbedtls/tls.c
index cb0a4bbf..ca6c716c 100644
--- a/src/supplemental/tls/mbedtls/tls.c
+++ b/src/supplemental/tls/mbedtls/tls.c
@@ -642,11 +642,11 @@ nni_tls_do_send(nni_tls *tp)
uint8_t *buf = NULL;
size_t len = 0;
nni_iov *iov;
- int niov;
+ unsigned niov;
nni_aio_get_iov(aio, &niov, &iov);
- for (int i = 0; i < niov; i++) {
+ for (unsigned i = 0; i < niov; i++) {
if (iov[i].iov_len != 0) {
buf = iov[i].iov_buf;
len = iov[i].iov_len;
@@ -688,11 +688,11 @@ nni_tls_do_recv(nni_tls *tp)
uint8_t *buf = NULL;
size_t len = 0;
nni_iov *iov;
- int niov;
+ unsigned niov;
nni_aio_get_iov(aio, &niov, &iov);
- for (int i = 0; i < niov; i++) {
+ for (unsigned i = 0; i < niov; i++) {
if (iov[i].iov_len != 0) {
buf = iov[i].iov_buf;
len = iov[i].iov_len;