Skip to content

Commit 8f995c5

Browse files
committed
Wire: limit TX buffer size to avoid consuming too much stack
If data size to be sent is greater than the max defined, application can split the transfert Note: no limit implemented in RX buffer, because when receiving, data are received on I2C, it is not possible to split. Fixes #1539 Signed-off-by: Alexandre Bourdiol <[email protected]>
1 parent 6b1c62e commit 8f995c5

File tree

2 files changed

+20
-9
lines changed

2 files changed

+20
-9
lines changed

Diff for: libraries/Wire/src/Wire.cpp

+14-8
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,10 @@ size_t TwoWire::write(uint8_t data)
289289
size_t ret = 1;
290290
if (transmitting) {
291291
// in master transmitter mode
292-
allocateTxBuffer(txDataSize + 1);
293-
// error if no memory block available to allocate the buffer
294-
if (txBuffer == nullptr) {
292+
if (allocateTxBuffer(txDataSize + 1) == 0) {
293+
ret = 0;
294+
} else if (txBuffer == nullptr) {
295+
// error if no memory block available to allocate the buffer
295296
setWriteError();
296297
ret = 0;
297298
} else {
@@ -323,9 +324,10 @@ size_t TwoWire::write(const uint8_t *data, size_t quantity)
323324

324325
if (transmitting) {
325326
// in master transmitter mode
326-
allocateTxBuffer(txDataSize + quantity);
327-
// error if no memory block available to allocate the buffer
328-
if (txBuffer == nullptr) {
327+
if (allocateTxBuffer(txDataSize + quantity) == 0) {
328+
ret = 0;
329+
} else if (txBuffer == nullptr) {
330+
// error if no memory block available to allocate the buffer
329331
setWriteError();
330332
ret = 0;
331333
} else {
@@ -479,9 +481,12 @@ void TwoWire::allocateRxBuffer(size_t length)
479481
}
480482
}
481483

482-
inline void TwoWire::allocateTxBuffer(size_t length)
484+
inline size_t TwoWire::allocateTxBuffer(size_t length)
483485
{
484-
if (txBufferAllocated < length) {
486+
size_t ret = length;
487+
if (length > WIRE_MAX_TX_BUFF_LENGTH) {
488+
ret = 0;
489+
} else if (txBufferAllocated < length) {
485490
// By default we allocate BUFFER_LENGTH bytes. It is the min size of the buffer.
486491
if (length < BUFFER_LENGTH) {
487492
length = BUFFER_LENGTH;
@@ -494,6 +499,7 @@ inline void TwoWire::allocateTxBuffer(size_t length)
494499
_Error_Handler("No enough memory! (%i)\n", length);
495500
}
496501
}
502+
return ret;
497503
}
498504

499505
/**

Diff for: libraries/Wire/src/Wire.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ extern "C" {
2828
#include "utility/twi.h"
2929
}
3030

31+
// Minimal buffer length. Buffers length will be increased when needed,
32+
// but TX buffer is limited to a maximum to avoid too much stack consumption
3133
#define BUFFER_LENGTH 32
34+
#if !defined(WIRE_MAX_TX_BUFF_LENGTH)
35+
#define WIRE_MAX_TX_BUFF_LENGTH 1000U
36+
#endif
3237

3338
// WIRE_HAS_END means Wire has end()
3439
#define WIRE_HAS_END 1
@@ -56,7 +61,7 @@ class TwoWire : public Stream {
5661
static void onReceiveService(i2c_t *);
5762

5863
void allocateRxBuffer(size_t length);
59-
void allocateTxBuffer(size_t length);
64+
size_t allocateTxBuffer(size_t length);
6065

6166
void resetRxBuffer(void);
6267
void resetTxBuffer(void);

0 commit comments

Comments
 (0)