Skip to content

Commit 5b767a3

Browse files
new w/ OOM now aborts by defaults, or throw an exception (#7536)
* replace `new` by `new (std::nothrow)`, remove `arduino_new` * deleted: arduino_new/arduino_new.ino * fixes * remove (std::nothrow) where nullptr case is not handled remove legacy new management * new w/ OOM raises an exception, shows the caller address for decoders * overwrite weak `new (std::nothrow)` calls * fix displaying caller address * board generator: remove comments, remove now useless define Co-authored-by: Earle F. Philhower, III <[email protected]> Co-authored-by: Develo <[email protected]>
2 parents be812d2 + ef92ab2 commit 5b767a3

File tree

16 files changed

+134
-423
lines changed

16 files changed

+134
-423
lines changed

boards.txt

+68-170
Large diffs are not rendered by default.

cores/esp8266/Esp.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -740,17 +740,17 @@ String EspClass::getSketchMD5()
740740
}
741741
uint32_t lengthLeft = getSketchSize();
742742
const size_t bufSize = 512;
743-
std::unique_ptr<uint8_t[]> buf(new uint8_t[bufSize]);
743+
std::unique_ptr<uint8_t[]> buf(new (std::nothrow) uint8_t[bufSize]);
744744
uint32_t offset = 0;
745745
if(!buf.get()) {
746-
return String();
746+
return emptyString;
747747
}
748748
MD5Builder md5;
749749
md5.begin();
750750
while( lengthLeft > 0) {
751751
size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize;
752752
if (!flashRead(offset, reinterpret_cast<uint32_t*>(buf.get()), (readBytes + 3) & ~3)) {
753-
return String();
753+
return emptyString;
754754
}
755755
md5.add(buf.get(), readBytes);
756756
lengthLeft -= readBytes;

cores/esp8266/Print.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ size_t Print::printf(const char *format, ...) {
6363
size_t len = vsnprintf(temp, sizeof(temp), format, arg);
6464
va_end(arg);
6565
if (len > sizeof(temp) - 1) {
66-
buffer = new char[len + 1];
66+
buffer = new (std::nothrow) char[len + 1];
6767
if (!buffer) {
6868
return 0;
6969
}
@@ -86,7 +86,7 @@ size_t Print::printf_P(PGM_P format, ...) {
8686
size_t len = vsnprintf_P(temp, sizeof(temp), format, arg);
8787
va_end(arg);
8888
if (len > sizeof(temp) - 1) {
89-
buffer = new char[len + 1];
89+
buffer = new (std::nothrow) char[len + 1];
9090
if (!buffer) {
9191
return 0;
9292
}

cores/esp8266/abi.cpp

+31-5
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,33 @@ extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__));
3232
extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__));
3333

3434

35-
#if !defined(__cpp_exceptions) && !defined(NEW_OOM_ABORT)
36-
void *operator new(size_t size)
35+
#if !defined(__cpp_exceptions)
36+
37+
// overwrite weak operators new/new[] definitions
38+
39+
void* operator new(size_t size)
40+
{
41+
void *ret = malloc(size);
42+
if (0 != size && 0 == ret) {
43+
umm_last_fail_alloc_addr = __builtin_return_address(0);
44+
umm_last_fail_alloc_size = size;
45+
__unhandled_exception(PSTR("OOM"));
46+
}
47+
return ret;
48+
}
49+
50+
void* operator new[](size_t size)
3751
{
3852
void *ret = malloc(size);
3953
if (0 != size && 0 == ret) {
4054
umm_last_fail_alloc_addr = __builtin_return_address(0);
4155
umm_last_fail_alloc_size = size;
56+
__unhandled_exception(PSTR("OOM"));
4257
}
43-
return ret;
58+
return ret;
4459
}
4560

46-
void *operator new[](size_t size)
61+
void* operator new (size_t size, const std::nothrow_t&)
4762
{
4863
void *ret = malloc(size);
4964
if (0 != size && 0 == ret) {
@@ -52,7 +67,18 @@ void *operator new[](size_t size)
5267
}
5368
return ret;
5469
}
55-
#endif // arduino's std::new legacy
70+
71+
void* operator new[] (size_t size, const std::nothrow_t&)
72+
{
73+
void *ret = malloc(size);
74+
if (0 != size && 0 == ret) {
75+
umm_last_fail_alloc_addr = __builtin_return_address(0);
76+
umm_last_fail_alloc_size = size;
77+
}
78+
return ret;
79+
}
80+
81+
#endif // !defined(__cpp_exceptions)
5682

5783
void __cxa_pure_virtual(void)
5884
{

cores/esp8266/cbuf.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1919
*/
2020

21+
#include <new> // std::nothrow
2122
#include "cbuf.h"
2223
#include "c_types.h"
2324

@@ -43,7 +44,7 @@ size_t cbuf::resize(size_t newSize) {
4344
return _size;
4445
}
4546

46-
char *newbuf = new char[newSize];
47+
char *newbuf = new (std::nothrow) char[newSize];
4748
char *oldbuf = _buf;
4849

4950
if(!newbuf) {

cores/esp8266/core_esp8266_features.h

-29
Original file line numberDiff line numberDiff line change
@@ -36,35 +36,6 @@
3636
#include <stddef.h> // size_t
3737
#include <stdint.h>
3838

39-
#ifdef __cplusplus
40-
41-
namespace arduino
42-
{
43-
extern "C++"
44-
template <typename T, typename ...TConstructorArgs>
45-
T* new0 (size_t n, TConstructorArgs... TconstructorArgs)
46-
{
47-
// n==0: single allocation, otherwise it is an array
48-
size_t offset = n? sizeof(size_t): 0;
49-
size_t arraysize = n? n: 1;
50-
T* ptr = (T*)malloc(offset + (arraysize * sizeof(T)));
51-
if (ptr)
52-
{
53-
if (n)
54-
*(size_t*)(ptr) = n;
55-
for (size_t i = 0; i < arraysize; i++)
56-
new (ptr + offset + i * sizeof(T)) T(TconstructorArgs...);
57-
return ptr + offset;
58-
}
59-
return nullptr;
60-
}
61-
}
62-
63-
#define arduino_new(Type, ...) arduino::new0<Type>(0, ##__VA_ARGS__)
64-
#define arduino_newarray(Type, n, ...) arduino::new0<Type>(n, ##__VA_ARGS__)
65-
66-
#endif // __cplusplus
67-
6839
#ifndef __STRINGIFY
6940
#define __STRINGIFY(a) #a
7041
#endif

cores/esp8266/core_esp8266_postmortem.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,12 @@ void __wrap_system_restart_local() {
220220

221221
cut_here();
222222

223+
if (s_unhandled_exception && umm_last_fail_alloc_addr) {
224+
// now outside from the "cut-here" zone, print correctly the `new` caller address,
225+
// idf-monitor.py will be able to decode this one and show exact location in sources
226+
ets_printf_P(PSTR("\nlast failed alloc caller: 0x%08x\n"), (uint32_t)umm_last_fail_alloc_addr);
227+
}
228+
223229
custom_crash_callback( &rst_info, sp_dump + offset, stack_end );
224230

225231
ets_delay_us(10000);

cores/esp8266/debug.h

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ void hexdump(const void *mem, uint32_t len, uint8_t cols);
2222
extern "C" {
2323
#endif
2424

25+
void __unhandled_exception(const char *str) __attribute__((noreturn));
2526
void __panic_func(const char* file, int line, const char* func) __attribute__((noreturn));
2627
#define panic() __panic_func(PSTR(__FILE__), __LINE__, __func__)
2728

doc/reference.rst

-33
Original file line numberDiff line numberDiff line change
@@ -323,36 +323,3 @@ C++
323323
This assures correct behavior, including handling of all subobjects, which guarantees stability.
324324

325325
History: `#6269 <https://github.com/esp8266/Arduino/issues/6269>`__ `#6309 <https://github.com/esp8266/Arduino/pull/6309>`__ `#6312 <https://github.com/esp8266/Arduino/pull/6312>`__
326-
327-
- New optional allocator ``arduino_new``
328-
329-
A new optional global allocator is introduced with a different semantic:
330-
331-
- never throws exceptions on oom
332-
333-
- never calls constructors on oom
334-
335-
- returns nullptr on oom
336-
337-
It is similar to arduino ``new`` semantic without side effects
338-
(except when parent constructors, or member constructors use ``new``).
339-
340-
Syntax is slightly different, the following shows the different usages:
341-
342-
.. code:: cpp
343-
344-
// with new:
345-
346-
SomeClass* sc = new SomeClass(arg1, arg2, ...);
347-
delete sc;
348-
349-
SomeClass* scs = new SomeClass[42];
350-
delete [] scs;
351-
352-
// with arduino_new:
353-
354-
SomeClass* sc = arduino_new(SomeClass, arg1, arg2, ...);
355-
delete sc;
356-
357-
SomeClass* scs = arduino_newarray(SomeClass, 42);
358-
delete [] scs;

libraries/DNSServer/src/DNSServer.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,7 @@ void DNSServer::processNextRequest()
178178
return;
179179

180180
std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[currentPacketSize]);
181-
182-
if (buffer == NULL)
181+
if (buffer == nullptr)
183182
return;
184183

185184
_udp.read(buffer.get(), currentPacketSize);

libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ bool HTTPClient::begin(String url, const uint8_t httpsFingerprint[20])
182182
if (!beginInternal(url, "https")) {
183183
return false;
184184
}
185-
_transportTraits = TransportTraitsPtr(new BearSSLTraits(httpsFingerprint));
185+
_transportTraits = TransportTraitsPtr(new (std::nothrow) BearSSLTraits(httpsFingerprint));
186186
if(!_transportTraits) {
187187
DEBUG_HTTPCLIENT("[HTTP-Client][begin] could not create transport traits\n");
188188
return false;

libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,12 @@ bool ESP8266WebServerTemplate<ServerType>::authenticate(const char * username, c
126126
authReq = authReq.substring(6);
127127
authReq.trim();
128128
char toencodeLen = strlen(username)+strlen(password)+1;
129-
char *toencode = new char[toencodeLen + 1];
129+
char *toencode = new (std::nothrow) char[toencodeLen + 1];
130130
if(toencode == NULL){
131131
authReq = "";
132132
return false;
133133
}
134-
char *encoded = new char[base64_encode_expected_len(toencodeLen)+1];
134+
char *encoded = new (std::nothrow) char[base64_encode_expected_len(toencodeLen)+1];
135135
if(encoded == NULL){
136136
authReq = "";
137137
delete[] toencode;

libraries/ESP8266WiFi/src/CertStoreBearSSL.cpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,13 @@ CertStore::CertInfo CertStore::_preprocessCert(uint32_t length, uint32_t offset,
5050
memset(&ci, 0, sizeof(ci));
5151

5252
// Process it using SHA256, same as the hashed_dn
53-
br_x509_decoder_context *ctx = new br_x509_decoder_context;
54-
br_sha256_context *sha256 = new br_sha256_context;
53+
br_x509_decoder_context *ctx = new (std::nothrow) br_x509_decoder_context;
54+
br_sha256_context *sha256 = new (std::nothrow) br_sha256_context;
5555
if (!ctx || !sha256) {
56+
if (ctx)
57+
delete ctx;
58+
if (sha256)
59+
delete sha256;
5660
DEBUG_BSSL("CertStore::_preprocessCert: OOM\n");
5761
return ci;
5862
}
@@ -202,7 +206,7 @@ const br_x509_trust_anchor *CertStore::findHashedTA(void *ctx, void *hashed_dn,
202206
return nullptr;
203207
}
204208
data.close();
205-
cs->_x509 = new X509List(der, ci.length);
209+
cs->_x509 = new (std::nothrow) X509List(der, ci.length);
206210
free(der);
207211
if (!cs->_x509) {
208212
DEBUG_BSSL("CertStore::findHashedTA: OOM\n");

libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.cpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,7 @@ extern "C" {
977977
// Set custom list of ciphers
978978
bool WiFiClientSecure::setCiphers(const uint16_t *cipherAry, int cipherCount) {
979979
_cipher_list = nullptr;
980-
_cipher_list = std::shared_ptr<uint16_t>(new uint16_t[cipherCount], std::default_delete<uint16_t[]>());
980+
_cipher_list = std::shared_ptr<uint16_t>(new (std::nothrow) uint16_t[cipherCount], std::default_delete<uint16_t[]>());
981981
if (!_cipher_list.get()) {
982982
DEBUG_BSSL("setCiphers: list empty\n");
983983
return false;
@@ -1067,8 +1067,8 @@ bool WiFiClientSecure::_connectSSL(const char* hostName) {
10671067

10681068
_sc = std::make_shared<br_ssl_client_context>();
10691069
_eng = &_sc->eng; // Allocation/deallocation taken care of by the _sc shared_ptr
1070-
_iobuf_in = std::shared_ptr<unsigned char>(new unsigned char[_iobuf_in_size], std::default_delete<unsigned char[]>());
1071-
_iobuf_out = std::shared_ptr<unsigned char>(new unsigned char[_iobuf_out_size], std::default_delete<unsigned char[]>());
1070+
_iobuf_in = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_in_size], std::default_delete<unsigned char[]>());
1071+
_iobuf_out = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_out_size], std::default_delete<unsigned char[]>());
10721072

10731073
if (!_sc || !_iobuf_in || !_iobuf_out) {
10741074
_freeSSL(); // Frees _sc, _iobuf*
@@ -1183,8 +1183,8 @@ bool WiFiClientSecure::_connectSSLServerRSA(const X509List *chain,
11831183
_oom_err = false;
11841184
_sc_svr = std::make_shared<br_ssl_server_context>();
11851185
_eng = &_sc_svr->eng; // Allocation/deallocation taken care of by the _sc shared_ptr
1186-
_iobuf_in = std::shared_ptr<unsigned char>(new unsigned char[_iobuf_in_size], std::default_delete<unsigned char[]>());
1187-
_iobuf_out = std::shared_ptr<unsigned char>(new unsigned char[_iobuf_out_size], std::default_delete<unsigned char[]>());
1186+
_iobuf_in = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_in_size], std::default_delete<unsigned char[]>());
1187+
_iobuf_out = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_out_size], std::default_delete<unsigned char[]>());
11881188

11891189
if (!_sc_svr || !_iobuf_in || !_iobuf_out) {
11901190
_freeSSL();
@@ -1220,8 +1220,8 @@ bool WiFiClientSecure::_connectSSLServerEC(const X509List *chain,
12201220
_oom_err = false;
12211221
_sc_svr = std::make_shared<br_ssl_server_context>();
12221222
_eng = &_sc_svr->eng; // Allocation/deallocation taken care of by the _sc shared_ptr
1223-
_iobuf_in = std::shared_ptr<unsigned char>(new unsigned char[_iobuf_in_size], std::default_delete<unsigned char[]>());
1224-
_iobuf_out = std::shared_ptr<unsigned char>(new unsigned char[_iobuf_out_size], std::default_delete<unsigned char[]>());
1223+
_iobuf_in = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_in_size], std::default_delete<unsigned char[]>());
1224+
_iobuf_out = std::shared_ptr<unsigned char>(new (std::nothrow) unsigned char[_iobuf_out_size], std::default_delete<unsigned char[]>());
12251225

12261226
if (!_sc_svr || !_iobuf_in || !_iobuf_out) {
12271227
_freeSSL();
@@ -1421,7 +1421,7 @@ bool WiFiClientSecure::probeMaxFragmentLength(IPAddress ip, uint16_t port, uint1
14211421
default: return false; // Invalid size
14221422
}
14231423
int ttlLen = sizeof(clientHelloHead_P) + (2 + sizeof(suites_P)) + (sizeof(clientHelloTail_P) + 1);
1424-
uint8_t *clientHello = new uint8_t[ttlLen];
1424+
uint8_t *clientHello = new (std::nothrow) uint8_t[ttlLen];
14251425
if (!clientHello) {
14261426
DEBUG_BSSL("probeMaxFragmentLength: OOM\n");
14271427
return false;

0 commit comments

Comments
 (0)