aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/buffer.h8
-rw-r--r--src/buffer.c18
-rw-r--r--tests/unittests/torture_buffer.c8
3 files changed, 29 insertions, 5 deletions
diff --git a/include/libssh/buffer.h b/include/libssh/buffer.h
index dec11739..4a50bcc7 100644
--- a/include/libssh/buffer.h
+++ b/include/libssh/buffer.h
@@ -23,7 +23,13 @@
#define BUFFER_H_
#include "libssh/libssh.h"
-/* Describes a buffer state */
+/*
+ * Describes a buffer state
+ * [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX]
+ * ^ ^ ^ ^]
+ * \_data points\_pos points here \_used points here | /
+ * here Allocated
+ */
struct ssh_buffer_struct {
char *data;
uint32_t used;
diff --git a/src/buffer.c b/src/buffer.c
index 465f618a..fd07177c 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -293,14 +293,24 @@ int buffer_add_u8(struct ssh_buffer_struct *buffer,uint8_t data){
int buffer_prepend_data(struct ssh_buffer_struct *buffer, const void *data,
uint32_t len) {
buffer_verify(buffer);
- if (buffer->allocated < (buffer->used + len)) {
- if (realloc_buffer(buffer, buffer->used + len) < 0) {
+
+ if(len <= buffer->pos){
+ /* It's possible to insert data between begin and pos */
+ memcpy(buffer->data + (buffer->pos - len), data, len);
+ buffer->pos -= len;
+ buffer_verify(buffer);
+ return 0;
+ }
+ /* pos isn't high enough */
+ if (buffer->allocated < (buffer->used - buffer->pos + len)) {
+ if (realloc_buffer(buffer, buffer->used - buffer->pos + len) < 0) {
return -1;
}
}
- memmove(buffer->data + len, buffer->data, buffer->used);
+ memmove(buffer->data + len, buffer->data + buffer->pos, buffer->used - buffer->pos);
memcpy(buffer->data, data, len);
- buffer->used += len;
+ buffer->used += len - buffer->pos;
+ buffer->pos = 0;
buffer_verify(buffer);
return 0;
}
diff --git a/tests/unittests/torture_buffer.c b/tests/unittests/torture_buffer.c
index 60712a81..5653c4db 100644
--- a/tests/unittests/torture_buffer.c
+++ b/tests/unittests/torture_buffer.c
@@ -70,6 +70,14 @@ START_TEST (torture_buffer_prepend)
buffer_prepend_data(buffer,"aris",4);
ck_assert_int_eq(buffer_get_rest_len(buffer),9);
ck_assert_int_eq(memcmp(buffer_get_rest(buffer), "arisbcdef", 9), 0);
+ /* same thing but we add 5 bytes now */
+ buffer_get_u32(buffer,&v);
+ ck_assert_int_eq(buffer_get_rest_len(buffer),5);
+ ck_assert_int_eq(memcmp(buffer_get_rest(buffer), "bcdef", 5), 0);
+ buffer_prepend_data(buffer,"12345",5);
+ ck_assert_int_eq(buffer_get_rest_len(buffer),10);
+ ck_assert_int_eq(memcmp(buffer_get_rest(buffer), "12345bcdef", 10), 0);
+
}
END_TEST