Skip to content

Commit 63e4680

Browse files
author
Arto Kinnunen
authored
Allow buffer_dyn to handle more data (ARMmbed#2311)
Buffer fails to handle more than INT16_MAX bytes of data. To fix the problem: -Modify buffer checks to allow handling of 65532 (0xFFFC) bytes of data (as we have 16-bit counters). -Deny allocation of buffer that have more than 0xFFFF bytes of data.
1 parent 9b82abf commit 63e4680

File tree

5 files changed

+172
-19
lines changed

5 files changed

+172
-19
lines changed

source/Core/buffer_dyn.c

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

1818
#include "nsconfig.h"
19-
#include "string.h"
19+
#include <string.h>
20+
#include <limits.h>
2021
#include "ns_types.h"
2122
#include "nsdynmemLIB.h"
2223
#include "Core/include/ns_address_internal.h"
@@ -30,6 +31,13 @@
3031

3132
#define TRACE_GROUP "buff"
3233

34+
// Get module working also on 16-bit platform
35+
#if INT_MAX < 0xFFFF
36+
#define BUFFER_MAX_SIZE ((size_t)INT_MAX)
37+
#else
38+
#define BUFFER_MAX_SIZE ((size_t)0xFFFF)
39+
#endif
40+
3341
volatile unsigned int buffer_count = 0;
3442

3543
uint8_t *(buffer_corrupt_check)(buffer_t *buf)
@@ -38,15 +46,12 @@ uint8_t *(buffer_corrupt_check)(buffer_t *buf)
3846
return NULL;
3947
}
4048

41-
if (buf->buf_ptr > buf->buf_end) {
42-
tr_error("Buffer pointer end not set");
43-
} else if (buffer_data_length(buf) < 0) {
44-
tr_error("Buffer length overflow");
45-
while (1);
46-
} else if (buf->buf_end > buf->size || buf->buf_ptr > buf->size) {
47-
tr_error("buffer pointer overridden");
49+
if (buf->buf_ptr > buf->buf_end || buf->buf_end > buf->size) {
50+
tr_error("Invalid buffer, size=%"PRIu16", buf_ptr=%"PRIu16", buf_end=%"PRIu16"", buf->size, buf->buf_ptr, buf->buf_end);
51+
tr_error("Data: %s", tr_array(buffer_data_pointer(buf), 56));
4852
while (1);
4953
}
54+
5055
return buffer_data_pointer(buf);
5156
}
5257

@@ -71,8 +76,8 @@ buffer_t *buffer_get_minimal(uint16_t size)
7176
*/
7277
buffer_t *buffer_get_specific(uint16_t headroom, uint16_t size, uint16_t minspace)
7378
{
74-
buffer_t *buf;
75-
uint16_t total_size;
79+
buffer_t *buf = NULL;
80+
uint32_t total_size;
7681

7782
total_size = headroom + size;
7883
if (total_size < minspace) {
@@ -83,10 +88,12 @@ buffer_t *buffer_get_specific(uint16_t headroom, uint16_t size, uint16_t minspac
8388
* anyway be this much aligned. */
8489
total_size = (total_size + 3) & ~ 3;
8590

86-
// Note - as well as this alloc+init, buffers can also be "realloced"
87-
// in buffer_headroom()
91+
if (total_size <= BUFFER_MAX_SIZE) {
92+
// Note - as well as this alloc+init, buffers can also be "realloced"
93+
// in buffer_headroom()
94+
buf = ns_dyn_mem_temporary_alloc(sizeof(buffer_t) + total_size);
95+
}
8896

89-
buf = ns_dyn_mem_temporary_alloc(sizeof(buffer_t) + total_size);
9097
if (buf) {
9198
platform_enter_critical();
9299
buffer_count++;
@@ -110,7 +117,7 @@ buffer_t *buffer_get_specific(uint16_t headroom, uint16_t size, uint16_t minspac
110117
#endif
111118
buf->size = total_size;
112119
} else {
113-
tr_error("buffer_get failed: alloc(%d)", (int) sizeof(buffer_t) + total_size);
120+
tr_error("buffer_get failed: alloc(%"PRIu32")", (uint32_t)(sizeof(buffer_t) + total_size));
114121
}
115122

116123
protocol_stats_update(STATS_BUFFER_ALLOC, 1);
@@ -130,10 +137,14 @@ buffer_t *buffer_headroom(buffer_t *buf, uint16_t size)
130137
uint16_t curr_len = buffer_data_length(buf);
131138

132139
if (buf->size < (curr_len + size)) {
140+
buffer_t *restrict new_buf = NULL;
133141
/* This buffer isn't big enough at all - allocate a new block */
134142
// TODO - should we be giving them extra? probably
135-
uint16_t new_total = (curr_len + size + 3) & ~ 3;
136-
buffer_t *restrict new_buf = ns_dyn_mem_temporary_alloc(sizeof(buffer_t) + new_total);
143+
uint32_t new_total = (curr_len + size + 3) & ~ 3;
144+
if (new_total <= BUFFER_MAX_SIZE) {
145+
new_buf = ns_dyn_mem_temporary_alloc(sizeof(buffer_t) + new_total);
146+
}
147+
137148
if (new_buf) {
138149
// Copy the buffer_t header
139150
*new_buf = *buf;

source/Core/include/ns_buffer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ struct socket *buffer_socket_set(buffer_t *buf, struct socket *socket);
322322
} while(0)
323323

324324
/** get data length*/
325-
#define buffer_data_length(x) (int16_t)(x->buf_end - x->buf_ptr)
325+
#define buffer_data_length(x) (int)(x->buf_end - x->buf_ptr)
326326

327327
/** get data length Set*/
328328
#define buffer_data_length_set(x,z) ((x)->buf_end = (x)->buf_ptr + (z))

test/nanostack/unittest/Core/buffer_dyn/buffer_dyntest.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,7 @@ TEST(buffer_dyn, test_buffer_get)
3131
CHECK(test_buffer_get());
3232
}
3333

34+
TEST(buffer_dyn, test_buffer_get_minimal)
35+
{
36+
CHECK(test_buffer_get_minimal());
37+
}

test/nanostack/unittest/Core/buffer_dyn/test_buffer_dyn.c

Lines changed: 138 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,151 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
#include "test_buffer_dyn.h"
17+
18+
#include "nsconfig.h"
1819
#include <string.h>
20+
#include "ns_types.h"
21+
#include "ns_buffer.h"
22+
#include "test_buffer_dyn.h"
23+
#include "nsdynmemLIB_stub.h"
1924

25+
#define FILL_MARK 0x05
26+
bool test_buffer_get_and_data_add(uint16_t size, bool use_minimal);
27+
28+
29+
bool test_buffer_get_minimal_with_size(uint16_t size)
30+
{
31+
return test_buffer_get_and_data_add(size, true);
32+
}
33+
34+
bool test_buffer_get_with_size(uint16_t size)
35+
{
36+
return test_buffer_get_and_data_add(size, false);
37+
}
38+
39+
bool test_buffer_get_and_data_add(uint16_t size, bool use_minimal)
40+
{
41+
buffer_t *buf;
42+
uint8_t *data_ptr;
43+
uint16_t data_len;
44+
45+
nsdynmemlib_stub.returnCounter = 1;
46+
47+
data_len = size;
48+
49+
if (use_minimal) {
50+
buf = buffer_get_minimal(data_len);
51+
} else {
52+
buf = buffer_get(data_len);
53+
}
54+
if (!buf) {
55+
return false;
56+
}
57+
58+
// Add data to buffer
59+
data_ptr = malloc(data_len);
60+
memset(data_ptr, FILL_MARK, data_len);
61+
buffer_data_add(buf, data_ptr, data_len);
62+
63+
// validate content
64+
if (memcmp(buffer_data_pointer(buf), data_ptr, data_len) != 0) {
65+
return false;
66+
}
67+
68+
// validate buffer length
69+
if (buffer_data_length(buf) != data_len) {
70+
return false;
71+
}
72+
73+
buffer_free(buf);
74+
free(data_ptr);
75+
76+
return true;
77+
}
2078

2179
bool test_buffer_get()
2280
{
23-
if (buffer_get(1)) {
81+
buffer_t *buf;
82+
uint8_t *data_ptr;
83+
uint16_t data_len;
84+
85+
// memory allocation failure
86+
buf = buffer_get(1);
87+
if (buf) {
88+
return false;
89+
}
90+
91+
// Test with (0xffff - BUFFER_DEFAULT_HEADROOM) aligned)
92+
uint16_t len = (0xffff - BUFFER_DEFAULT_HEADROOM - 4) + 3 & ~ 3;
93+
if (test_buffer_get_with_size(len) == false) {
2494
return false;
2595
}
96+
97+
len = len + 1;
98+
if (test_buffer_get_with_size(len) == true) {
99+
return false;
100+
}
101+
102+
// Test with 32767
103+
if (test_buffer_get_with_size(0x7fff) == false) {
104+
return false;
105+
}
106+
107+
// Test with 32768
108+
if (test_buffer_get_with_size(0x7fff + 1) == false) {
109+
return false;
110+
}
111+
112+
// test with 0-256
113+
for (int i = 0; i <= 256; i++) {
114+
if (test_buffer_get_with_size(i) == false) {
115+
return false;
116+
}
117+
}
118+
26119
return true;
27120
}
28121

122+
bool test_buffer_get_minimal()
123+
{
124+
buffer_t *buf;
125+
uint8_t *data_ptr;
126+
uint16_t data_len;
127+
128+
// memory allocation failure
129+
buf = buffer_get_minimal(1);
130+
if (buf) {
131+
return false;
132+
}
133+
134+
// Test with (0xffff - 4) aligned)
135+
uint16_t len = (0xffff - 4) + 3 & ~ 3;
136+
if (test_buffer_get_minimal_with_size(len) == false) {
137+
return false;
138+
}
139+
140+
// Test with too long size, fails
141+
len = len + 1;
142+
if (test_buffer_get_minimal_with_size(len) == true) {
143+
return false;
144+
}
145+
146+
// Test with 32767
147+
if (test_buffer_get_minimal_with_size(0x7fff) == false) {
148+
return false;
149+
}
150+
151+
// Test with 32768
152+
if (test_buffer_get_minimal_with_size(0x7fff + 1) == false) {
153+
return false;
154+
}
155+
156+
// test with 0-256
157+
for (int i = 0; i <= 256; i++) {
158+
if (test_buffer_get_minimal_with_size(i) == false) {
159+
return false;
160+
}
161+
}
162+
163+
return true;
164+
}

test/nanostack/unittest/Core/buffer_dyn/test_buffer_dyn.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ extern "C" {
2525

2626
bool test_buffer_get();
2727

28+
bool test_buffer_get_minimal();
29+
2830
#ifdef __cplusplus
2931
}
3032
#endif

0 commit comments

Comments
 (0)