Skip to content

Commit 0bbc3e2

Browse files
authored
Merge pull request #14740 from chrisswinchatt-arm/fix-netsocket-dynalloc
Fix 'netsocket: several dynamic allocation results not checked' (#14210) add_event_listener in NetworkInterface now returns an error if the method fails. Previous attempts to add the event listener would attempt to use an unchecked standard dynamically allocated ns_list_* item. In other cases, the dynamically allocated items will now be checked, and if unsuccessful, will return after cleaning up any outstanding issues. TCPSocket::accept will now check that its own internally allocated new TCPSocket call will succeed, and if not, will clean up the stack resources. This should help when memory is low but an incoming connection requests a connection when the TCPSocket is listening.
2 parents fa090ff + 053eb24 commit 0bbc3e2

File tree

7 files changed

+87
-10
lines changed

7 files changed

+87
-10
lines changed

connectivity/netsocket/include/netsocket/NetworkInterface.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,18 @@ class NetworkInterface: public DNS {
377377
*/
378378
virtual void attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
379379

380+
#if MBED_CONF_NSAPI_ADD_EVENT_LISTENER_RETURN_CHANGE
381+
/** Add event listener for interface.
382+
*
383+
* This API allows multiple callback to be registered for a single interface.
384+
* of both leads to undefined behavior.
385+
*
386+
* @param status_cb The callback for status changes.
387+
* @return NSAPI_ERROR_OK on success
388+
* @return NSAPI_ERROR_NO_MEMORY if the function fails to create a new entry.
389+
*/
390+
nsapi_error_t add_event_listener(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
391+
#else
380392
/** Add event listener for interface.
381393
*
382394
* This API allows multiple callback to be registered for a single interface.
@@ -386,9 +398,16 @@ class NetworkInterface: public DNS {
386398
* Application may only use attach() or add_event_listener() interface. Mixing usage
387399
* of both leads to undefined behavior.
388400
*
401+
* @warning This version of the function does not use the `std::nothrow` feature. Subsequently,
402+
* the function may fail to allocate memory and cause a system error. To use the new
403+
* version with the changes, set "nsapi.add-event-listener-return-change": 1 in the
404+
* target overrides section in your mbed_app.json file.
405+
*
389406
* @param status_cb The callback for status changes.
390407
*/
408+
MBED_DEPRECATED_SINCE("mbed-os-6.12", "This function return value will change to nsapi_error_t in the next major release. See documentation for details.")
391409
void add_event_listener(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
410+
#endif
392411

393412
#if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE
394413
/** Remove event listener from interface.
@@ -512,6 +531,10 @@ class NetworkInterface: public DNS {
512531
* configuration).
513532
*/
514533
virtual void set_default_parameters();
534+
535+
private:
536+
// Unified implementation for different versions of add_event_listener.
537+
nsapi_error_t internal_add_event_listener(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb);
515538
};
516539

517540
#endif

connectivity/netsocket/mbed_lib.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
"name": "nsapi",
33
"config": {
44
"present": 1,
5+
"add-event-listener-return-change": {
6+
"help": "Updates the add_event_listener to return a nsapi_error_t value which can indicate allocation failure. See documents for more details.",
7+
"value": 0
8+
},
59
"default-stack": {
610
"help" : "Default stack to be used, valid values: LWIP, NANOSTACK.",
711
"value" : "LWIP"

connectivity/netsocket/source/NetworkInterface.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "netsocket/NetworkStack.h"
2121
#include "platform/Callback.h"
2222
#include "platform/mbed_error.h"
23+
#include <new>
2324
#include <string.h>
2425

2526
// Default network-interface state
@@ -142,22 +143,48 @@ static void call_all_event_listeners(NetworkInterface *iface, nsapi_event_t even
142143
}
143144
}
144145

145-
void NetworkInterface::add_event_listener(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
146+
nsapi_error_t NetworkInterface::internal_add_event_listener(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
146147
{
147148
iface_eventlist_t *event_list = get_interface_event_list_head();
148149
#if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE
149150
ns_list_foreach_safe(iface_eventlist_entry_t, entry, event_list) {
150151
if (entry->status_cb == status_cb && entry->iface == this) {
151-
return;
152+
return NSAPI_ERROR_OK;
152153
}
153154
}
154155
#endif
155-
iface_eventlist_entry_t *entry = new iface_eventlist_entry_t;
156+
157+
iface_eventlist_entry_t *entry = new (std::nothrow) iface_eventlist_entry_t;
158+
if (!entry) {
159+
return NSAPI_ERROR_NO_MEMORY;
160+
}
161+
156162
entry->iface = this;
157163
entry->status_cb = status_cb;
158164
ns_list_add_to_end(event_list, entry);
159165
attach(mbed::callback(&call_all_event_listeners, this));
166+
return NSAPI_ERROR_OK;
167+
}
168+
169+
#if MBED_CONF_NSAPI_ADD_EVENT_LISTENER_RETURN_CHANGE
170+
nsapi_error_t NetworkInterface::add_event_listener(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
171+
{
172+
return internal_add_event_listener(status_cb);
173+
}
174+
#else
175+
void NetworkInterface::add_event_listener(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
176+
{
177+
auto error = internal_add_event_listener(status_cb);
178+
switch (error) {
179+
case NSAPI_ERROR_OK:
180+
return;
181+
case NSAPI_ERROR_NO_MEMORY:
182+
MBED_ERROR(error, "Out of memory when adding an event listener");
183+
default:
184+
MBED_UNREACHABLE;
185+
}
160186
}
187+
#endif // MBED_CONF_NSAPI_ADD_EVENT_LISTENER_RETURN_CHANGE
161188

162189
#if MBED_CONF_PLATFORM_CALLBACK_COMPARABLE
163190
void NetworkInterface::remove_event_listener(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)

connectivity/netsocket/source/TCPSocket.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717

1818
#include "netsocket/TCPSocket.h"
19+
#include <new>
1920
#include "Timer.h"
2021
#include "mbed_assert.h"
2122

@@ -266,7 +267,12 @@ TCPSocket *TCPSocket::accept(nsapi_error_t *error)
266267
ret = _stack->socket_accept(_socket, &socket, &address);
267268

268269
if (0 == ret) {
269-
connection = new TCPSocket(this, socket, address);
270+
connection = new (std::nothrow) TCPSocket(this, socket, address);
271+
if (!connection) {
272+
ret = NSAPI_ERROR_NO_MEMORY;
273+
break;
274+
}
275+
270276
_socket_stats.stats_update_peer(connection, address);
271277
_socket_stats.stats_update_socket_state(connection, SOCK_CONNECTED);
272278
break;

connectivity/netsocket/source/TLSSocketWrapper.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717

1818
#include "netsocket/TLSSocketWrapper.h"
19+
#include <new>
1920
#include "platform/Callback.h"
2021
#include "drivers/Timer.h"
2122
#include "events/mbed_events.h"
@@ -134,7 +135,10 @@ nsapi_error_t TLSSocketWrapper::set_client_cert_key(const void *client_cert, siz
134135
#else
135136

136137
int ret;
137-
mbedtls_x509_crt *crt = new mbedtls_x509_crt;
138+
mbedtls_x509_crt *crt = new (std::nothrow) mbedtls_x509_crt;
139+
if (!crt) {
140+
return NSAPI_ERROR_NO_MEMORY;
141+
}
138142
mbedtls_x509_crt_init(crt);
139143
if ((ret = mbedtls_x509_crt_parse(crt, static_cast<const unsigned char *>(client_cert),
140144
client_cert_len)) != 0) {
@@ -286,7 +290,11 @@ nsapi_error_t TLSSocketWrapper::continue_handshake()
286290
#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(FEA_TRACE_SUPPORT) && !defined(MBEDTLS_X509_REMOVE_INFO)
287291
/* Prints the server certificate and verify it. */
288292
const size_t buf_size = 1024;
289-
char *buf = new char[buf_size];
293+
char *buf = new (std::nothrow) char[buf_size];
294+
if (!buf) {
295+
print_mbedtls_error("new (std::nothrow) char[buf_size] failed in continue_handshake", NSAPI_ERROR_NO_MEMORY);
296+
return NSAPI_ERROR_NO_MEMORY;
297+
}
290298
mbedtls_x509_crt_info(buf, buf_size, "\r ",
291299
mbedtls_ssl_get_peer_cert(&_ssl));
292300
tr_debug("Server certificate:\r\n%s\r\n", buf);
@@ -427,10 +435,9 @@ void TLSSocketWrapper::print_mbedtls_error(MBED_UNUSED const char *name, MBED_UN
427435
{
428436
// Avoid pulling in mbedtls_strerror when trace is not enabled
429437
#if defined FEA_TRACE_SUPPORT && defined MBEDTLS_ERROR_C
430-
char *buf = new char[128];
438+
char buf[128];
431439
mbedtls_strerror(err, buf, 128);
432440
tr_err("%s() failed: -0x%04x (%d): %s", name, -err, err, buf);
433-
delete[] buf;
434441
#else
435442
tr_err("%s() failed: -0x%04x (%d)", name, -err, err);
436443
#endif
@@ -569,7 +576,10 @@ mbedtls_ssl_config *TLSSocketWrapper::get_ssl_config()
569576
{
570577
if (!_ssl_conf) {
571578
int ret;
572-
_ssl_conf = new mbedtls_ssl_config;
579+
_ssl_conf = new (std::nothrow) mbedtls_ssl_config;
580+
if (!_ssl_conf) {
581+
return nullptr;
582+
}
573583
mbedtls_ssl_config_init(_ssl_conf);
574584
_ssl_conf_allocated = true;
575585

connectivity/netsocket/source/nsapi_dns.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,12 @@ static void nsapi_dns_query_async_create(void *ptr)
982982
}
983983

984984
if (!query->socket_cb_data) {
985-
query->socket_cb_data = new SOCKET_CB_DATA;
985+
query->socket_cb_data = new (std::nothrow) SOCKET_CB_DATA;
986+
if (!query->socket_cb_data) {
987+
delete socket;
988+
nsapi_dns_query_async_resp(query, NSAPI_ERROR_NO_MEMORY, NULL);
989+
return;
990+
}
986991
}
987992
query->socket_cb_data->call_in_cb = query->call_in_cb;
988993
query->socket_cb_data->stack = query->stack;

tools/test/travis-ci/doxy-spellchecker/ignore.en.pws

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,5 @@ instantiation
121121
instantiations
122122
KVStore
123123
_doxy_
124+
nothrow
125+
conf

0 commit comments

Comments
 (0)