summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2014-04-22 23:00:06 +0200
committerAndreas Schneider <asn@cryptomilk.org>2014-08-06 09:58:52 +0200
commit3b4b0f01ecdc8b24cb10d871f200abb26bef1548 (patch)
treea438f0881b05e17a01bfb03b39abe2ef1caebeb8
parent7bd62dd652ba59c2ef4dfb9c3cc8d1262a48901d (diff)
downloadlibssh-3b4b0f01ecdc8b24cb10d871f200abb26bef1548.tar.gz
libssh-3b4b0f01ecdc8b24cb10d871f200abb26bef1548.tar.xz
libssh-3b4b0f01ecdc8b24cb10d871f200abb26bef1548.zip
buffer: add a hidden canary to detect format errors
Reviewed-by: Andreas Schneider <asn@samba.org>
-rw-r--r--include/libssh/buffer.h9
-rw-r--r--src/buffer.c19
2 files changed, 23 insertions, 5 deletions
diff --git a/include/libssh/buffer.h b/include/libssh/buffer.h
index 942089f0..a3e093c2 100644
--- a/include/libssh/buffer.h
+++ b/include/libssh/buffer.h
@@ -38,6 +38,8 @@ struct ssh_buffer_struct {
uint32_t pos;
};
+#define SSH_BUFFER_PACK_END ((uint32_t) 0x4f65feb3)
+
LIBSSH_API void ssh_buffer_free(ssh_buffer buffer);
LIBSSH_API void *ssh_buffer_get_begin(ssh_buffer buffer);
LIBSSH_API uint32_t ssh_buffer_get_len(ssh_buffer buffer);
@@ -49,9 +51,12 @@ int buffer_add_u32(ssh_buffer buffer, uint32_t data);
int buffer_add_u64(ssh_buffer buffer, uint64_t data);
int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len);
int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer, const char *format, va_list ap);
-int ssh_buffer_pack(struct ssh_buffer_struct *buffer, const char *format, ...);
+int _ssh_buffer_pack(struct ssh_buffer_struct *buffer, const char *format, ...);
+#define ssh_buffer_pack(buffer, format, ...) _ssh_buffer_pack((buffer),(format), __VA_ARGS__, SSH_BUFFER_PACK_END)
int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer, const char *format, va_list ap);
-int ssh_buffer_unpack(struct ssh_buffer_struct *buffer, const char *format, ...);
+int _ssh_buffer_unpack(struct ssh_buffer_struct *buffer, const char *format, ...);
+#define ssh_buffer_unpack(buffer, format, ...) _ssh_buffer_unpack((buffer),(format), __VA_ARGS__, SSH_BUFFER_PACK_END)
+
int buffer_prepend_data(ssh_buffer buffer, const void *data, uint32_t len);
int buffer_add_buffer(ssh_buffer buffer, ssh_buffer source);
int ssh_buffer_reinit(ssh_buffer buffer);
diff --git a/src/buffer.c b/src/buffer.c
index c2879b4b..7d4c7b3f 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -732,6 +732,13 @@ int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer, const char *format, va_
}
}
+ if (rc != SSH_ERROR){
+ /* verify that the last hidden argument is correct */
+ o.dword = va_arg(ap, uint32_t);
+ if (o.dword != SSH_BUFFER_PACK_END){
+ rc = SSH_ERROR;
+ }
+ }
return rc;
}
@@ -754,7 +761,7 @@ int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer, const char *format, va_
* @warning when using 'P' with a constant size (e.g. 8), do not
* forget to cast to (size_t).
*/
-int ssh_buffer_pack(struct ssh_buffer_struct *buffer, const char *format, ...){
+int _ssh_buffer_pack(struct ssh_buffer_struct *buffer, const char *format, ...){
va_list ap;
int rc;
@@ -876,7 +883,13 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer, const char *format, v
break;
}
}
-
+ if (rc != SSH_ERROR){
+ /* verify that the last hidden argument is correct */
+ uint32_t canary = va_arg(ap, uint32_t);
+ if (canary != SSH_BUFFER_PACK_END){
+ rc = SSH_ERROR;
+ }
+ }
if (rc != SSH_OK){
/* Reset the format string and erase everything that was allocated */
last = p;
@@ -930,7 +943,7 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer, const char *format, v
* @warning when using 'P' with a constant size (e.g. 8), do not
* forget to cast to (size_t).
*/
-int ssh_buffer_unpack(struct ssh_buffer_struct *buffer, const char *format, ...){
+int _ssh_buffer_unpack(struct ssh_buffer_struct *buffer, const char *format, ...){
va_list ap;
int rc;