Add error checking to buffer functions.

We don't check arguments cause we want a segfault here.


git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@312 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
Andreas Schneider
2009-04-01 09:36:44 +00:00
parent 8758b1260b
commit 98f78e1102
2 changed files with 172 additions and 106 deletions

View File

@@ -613,14 +613,14 @@ int ssh_options_default_ssh_dir(SSH_OPTIONS *opt);
int ssh_options_default_known_hosts_file(SSH_OPTIONS *opt); int ssh_options_default_known_hosts_file(SSH_OPTIONS *opt);
/* buffer.c */ /* buffer.c */
void buffer_add_ssh_string(BUFFER *buffer,STRING *string); int buffer_add_ssh_string(BUFFER *buffer, STRING *string);
void buffer_add_u8(BUFFER *buffer, u8 data); int buffer_add_u8(BUFFER *buffer, u8 data);
void buffer_add_u32(BUFFER *buffer, u32 data); int buffer_add_u32(BUFFER *buffer, u32 data);
void buffer_add_u64(BUFFER *buffer,u64 data); int buffer_add_u64(BUFFER *buffer, u64 data);
void buffer_add_data(BUFFER *buffer,const void *data, int len); int buffer_add_data(BUFFER *buffer, const void *data, u32 len);
void buffer_add_data_begin(BUFFER *buffer,const void *data,int len); int buffer_add_data_begin(BUFFER *buffer, const void *data, u32 len);
void buffer_add_buffer(BUFFER *buffer, BUFFER *source); int buffer_add_buffer(BUFFER *buffer, BUFFER *source);
void buffer_reinit(BUFFER *buffer); int buffer_reinit(BUFFER *buffer);
/* buffer_get_rest returns a pointer to the current position into the buffer */ /* buffer_get_rest returns a pointer to the current position into the buffer */
void *buffer_get_rest(BUFFER *buffer); void *buffer_get_rest(BUFFER *buffer);
@@ -628,8 +628,8 @@ void *buffer_get_rest(BUFFER *buffer);
u32 buffer_get_rest_len(BUFFER *buffer); u32 buffer_get_rest_len(BUFFER *buffer);
/* buffer_read_*() returns the number of bytes read, except for ssh strings */ /* buffer_read_*() returns the number of bytes read, except for ssh strings */
int buffer_get_u8(BUFFER *buffer,u8 *data); int buffer_get_u8(BUFFER *buffer, u8 *data);
int buffer_get_u32(BUFFER *buffer,u32 *data); int buffer_get_u32(BUFFER *buffer, u32 *data);
int buffer_get_u64(BUFFER *buffer, u64 *data); int buffer_get_u64(BUFFER *buffer, u64 *data);
u32 buffer_get_data(BUFFER *buffer, void *data, u32 requestedlen); u32 buffer_get_data(BUFFER *buffer, void *data, u32 requestedlen);

View File

@@ -36,50 +36,62 @@
*/ */
/** \brief creates a new buffer /** \brief creates a new buffer
* \return a new initialized buffer * \return a new initialized buffer, NULL on error.
*/ */
BUFFER *buffer_new(void) { struct buffer_struct *buffer_new(void) {
BUFFER *buffer=malloc(sizeof(BUFFER)); struct buffer_struct *buf = malloc(sizeof(struct buffer_struct));
memset(buffer,0,sizeof(BUFFER));
return buffer; if (buf == NULL) {
return NULL;
}
ZERO_STRUCTP(buf);
return buf;
} }
/** \brief deallocate a buffer /** \brief deallocate a buffer
* \param buffer buffer to free * \param buffer buffer to free
*/ */
void buffer_free(BUFFER *buffer){ void buffer_free(struct buffer_struct *buffer) {
// printf("buffer %p : free(%p);\n",buffer,buffer->data); if (buffer->data) {
if(buffer->data){ /* burn the data */
memset(buffer->data,0,buffer->allocated); /* burn the data */ memset(buffer->data, 0, buffer->allocated);
free(buffer->data); SAFE_FREE(buffer->data);
} }
memset(buffer,'x',sizeof (*buffer)); memset(buffer, 'X', sizeof(*buffer));
free(buffer); SAFE_FREE(buffer);
} }
static void realloc_buffer(BUFFER *buffer,int needed){ static int realloc_buffer(struct buffer_struct *buffer, int needed) {
int smallest=1; int smallest = 1;
// find the smallest power of two which is greater or equal to needed /* Find the smallest power of two which is greater or equal to needed */
while(smallest<=needed) while(smallest <= needed) {
smallest <<= 1; smallest <<= 1;
needed=smallest; }
// printf("buffer %p : realloc(%x,%d)=",buffer,buffer->data,needed); needed = smallest;
buffer->data=realloc(buffer->data,needed); buffer->data = realloc(buffer->data, needed);
// printf("%p\n",buffer->data); if (buffer->data == NULL) {
buffer->allocated=needed; return -1;
}
buffer->allocated = needed;
return 0;
} }
/* \internal /* \internal
* \brief reinitialize a buffer * \brief reinitialize a buffer
* \param buffer buffer * \param buffer buffer
* \return 0 on sucess, < 0 on error
*/ */
void buffer_reinit(BUFFER *buffer){ int buffer_reinit(struct buffer_struct *buffer) {
memset(buffer->data,0,buffer->used); memset(buffer->data, 0, buffer->used);
buffer->used=0; buffer->used = 0;
buffer->pos=0; buffer->pos = 0;
if(buffer->allocated > 127){ if(buffer->allocated > 127) {
realloc_buffer(buffer,127); if (realloc_buffer(buffer, 127) < 0) {
return -1;
} }
}
return 0;
} }
/** \internal /** \internal
@@ -88,45 +100,74 @@ void buffer_reinit(BUFFER *buffer){
* \param data data pointer * \param data data pointer
* \param len length of data * \param len length of data
*/ */
void buffer_add_data(BUFFER *buffer,const void *data,int len){ int buffer_add_data(struct buffer_struct *buffer, const void *data, u32 len) {
if(buffer->allocated < buffer->used+len) if (buffer->allocated < (buffer->used + len)) {
realloc_buffer(buffer,buffer->used+len); if (realloc_buffer(buffer, buffer->used + len) < 0) {
memcpy(buffer->data+buffer->used,data,len); return -1;
buffer->used+=len; }
}
memcpy(buffer->data+buffer->used, data, len);
buffer->used+=len;
return 0;
} }
/** \internal /** \internal
* \brief add a SSH string to the tail of buffer * \brief add a SSH string to the tail of buffer
* \param buffer buffer * \param buffer buffer
* \param string SSH String to add * \param string SSH String to add
* \return 0 on success, -1 on error.
*/ */
void buffer_add_ssh_string(BUFFER *buffer,STRING *string){ int buffer_add_ssh_string(struct buffer_struct *buffer,
u32 len=ntohl(string->size); struct string_struct *string) {
buffer_add_data(buffer,string,len+sizeof(u32)); u32 len = 0;
len = ntohl(string->size);
if (buffer_add_data(buffer, string, len + sizeof(u32)) < 0) {
return -1;
}
return 0;
} }
/** \internal /** \internal
* \brief add a 32 bits unsigned integer to the tail of buffer * \brief add a 32 bits unsigned integer to the tail of buffer
* \param buffer buffer * \param buffer buffer
* \param data 32 bits integer * \param data 32 bits integer
* \return 0 on success, -1 on error.
*/ */
void buffer_add_u32(BUFFER *buffer,u32 data){ int buffer_add_u32(struct buffer_struct *buffer,u32 data){
buffer_add_data(buffer,&data,sizeof(data)); if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
return -1;
}
return 0;
} }
/** \internal /** \internal
* \brief add a 64 bits unsigned integer to the tail of buffer * \brief add a 64 bits unsigned integer to the tail of buffer
* \param buffer buffer * \param buffer buffer
* \param data 64 bits integer * \param data 64 bits integer
* \return 0 on success, -1 on error.
*/ */
void buffer_add_u64(BUFFER *buffer,u64 data){ int buffer_add_u64(struct buffer_struct *buffer, u64 data){
buffer_add_data(buffer,&data,sizeof(data)); if (buffer_add_data(buffer, &data, sizeof(data)) < 0) {
return -1;
}
return 0;
} }
/** \internal /** \internal
* \brief add a 8 bits unsigned integer to the tail of buffer * \brief add a 8 bits unsigned integer to the tail of buffer
* \param buffer buffer * \param buffer buffer
* \param data 8 bits integer * \param data 8 bits integer
* \return 0 on success, -1 on error.
*/ */
void buffer_add_u8(BUFFER *buffer,u8 data){ int buffer_add_u8(struct buffer_struct *buffer,u8 data){
buffer_add_data(buffer,&data,sizeof(u8)); if (buffer_add_data(buffer, &data, sizeof(u8)) < 0) {
return -1;
}
return 0;
} }
/** \internal /** \internal
@@ -134,22 +175,34 @@ void buffer_add_u8(BUFFER *buffer,u8 data){
* \param buffer buffer * \param buffer buffer
* \param data data to add * \param data data to add
* \param len length of data * \param len length of data
* \return 0 on success, -1 on error.
*/ */
void buffer_add_data_begin(BUFFER *buffer, const void *data, int len){ int buffer_add_data_begin(struct buffer_struct *buffer, const void *data, u32 len) {
if(buffer->allocated < buffer->used + len) if (buffer->allocated < (buffer->used + len)) {
realloc_buffer(buffer,buffer->used+len); if (realloc_buffer(buffer, buffer->used + len) < 0) {
memmove(buffer->data+len,buffer->data,buffer->used); return -1;
memcpy(buffer->data,data,len); }
buffer->used+=len; }
memmove(buffer->data + len, buffer->data, buffer->used);
memcpy(buffer->data, data, len);
buffer->used += len;
return 0;
} }
/** \internal /** \internal
* \brief append data from a buffer to tail of another * \brief append data from a buffer to tail of another
* \param buffer destination buffer * \param buffer destination buffer
* \param source source buffer. Doesn't take position in buffer into account * \param source source buffer. Doesn't take position in buffer into account
* \return 0 on success, -1 on error.
*/ */
void buffer_add_buffer(BUFFER *buffer, BUFFER *source){ int buffer_add_buffer(struct buffer_struct *buffer,
buffer_add_data(buffer,buffer_get(source),buffer_get_len(source)); struct buffer_struct *source) {
if (buffer_add_data(buffer, buffer_get(source), buffer_get_len(source)) < 0) {
return -1;
}
return 0;
} }
/** \brief get a pointer on the head of the buffer /** \brief get a pointer on the head of the buffer
@@ -159,8 +212,8 @@ void buffer_add_buffer(BUFFER *buffer, BUFFER *source){
* \see buffer_get_rest() * \see buffer_get_rest()
* \see buffer_get_len() * \see buffer_get_len()
*/ */
void *buffer_get(BUFFER *buffer){ void *buffer_get(struct buffer_struct *buffer){
return buffer->data; return buffer->data;
} }
/** \internal /** \internal
@@ -170,8 +223,8 @@ void *buffer_get(BUFFER *buffer){
* \see buffer_get_rest_len() * \see buffer_get_rest_len()
* \see buffer_get() * \see buffer_get()
*/ */
void *buffer_get_rest(BUFFER *buffer){ void *buffer_get_rest(struct buffer_struct *buffer){
return buffer->data+buffer->pos; return buffer->data + buffer->pos;
} }
/** \brief get length of the buffer, not counting position /** \brief get length of the buffer, not counting position
@@ -179,7 +232,7 @@ void *buffer_get_rest(BUFFER *buffer){
* \return length of the buffer * \return length of the buffer
* \see buffer_get() * \see buffer_get()
*/ */
u32 buffer_get_len(BUFFER *buffer){ u32 buffer_get_len(struct buffer_struct *buffer){
return buffer->used; return buffer->used;
} }
@@ -189,7 +242,7 @@ u32 buffer_get_len(BUFFER *buffer){
* \return length of the buffer * \return length of the buffer
* \see buffer_get_rest() * \see buffer_get_rest()
*/ */
u32 buffer_get_rest_len(BUFFER *buffer){ u32 buffer_get_rest_len(struct buffer_struct *buffer){
return buffer->used - buffer->pos; return buffer->used - buffer->pos;
} }
@@ -200,7 +253,7 @@ u32 buffer_get_rest_len(BUFFER *buffer){
* \param len number of bytes to eat * \param len number of bytes to eat
* \return new size of the buffer * \return new size of the buffer
*/ */
u32 buffer_pass_bytes(BUFFER *buffer, u32 len){ u32 buffer_pass_bytes(struct buffer_struct *buffer, u32 len){
if(buffer->used < buffer->pos+len) if(buffer->used < buffer->pos+len)
return 0; return 0;
buffer->pos+=len; buffer->pos+=len;
@@ -218,7 +271,7 @@ u32 buffer_pass_bytes(BUFFER *buffer, u32 len){
* \param len number of bytes to remove from tail * \param len number of bytes to remove from tail
* \return new size of the buffer * \return new size of the buffer
*/ */
u32 buffer_pass_bytes_end(BUFFER *buffer, u32 len){ u32 buffer_pass_bytes_end(struct buffer_struct *buffer, u32 len){
if(buffer->used < buffer->pos + len) if(buffer->used < buffer->pos + len)
return 0; return 0;
buffer->used-=len; buffer->used-=len;
@@ -233,7 +286,7 @@ u32 buffer_pass_bytes_end(BUFFER *buffer, u32 len){
* \returns 0 if there is not enough data in buffer * \returns 0 if there is not enough data in buffer
* \returns len otherwise. * \returns len otherwise.
*/ */
u32 buffer_get_data(BUFFER *buffer, void *data, u32 len){ u32 buffer_get_data(struct buffer_struct *buffer, void *data, u32 len){
if(buffer->pos+len>buffer->used) if(buffer->pos+len>buffer->used)
return 0; /*no enough data in buffer */ return 0; /*no enough data in buffer */
memcpy(data,buffer->data+buffer->pos,len); memcpy(data,buffer->data+buffer->pos,len);
@@ -247,7 +300,7 @@ u32 buffer_get_data(BUFFER *buffer, void *data, u32 len){
* \returns 0 if there is not enough data in buffer * \returns 0 if there is not enough data in buffer
* \returns 1 otherwise. * \returns 1 otherwise.
*/ */
int buffer_get_u8(BUFFER *buffer, u8 *data){ int buffer_get_u8(struct buffer_struct *buffer, u8 *data){
return buffer_get_data(buffer,data,sizeof(u8)); return buffer_get_data(buffer,data,sizeof(u8));
} }
@@ -258,7 +311,7 @@ int buffer_get_u8(BUFFER *buffer, u8 *data){
* \returns 0 if there is not enough data in buffer * \returns 0 if there is not enough data in buffer
* \returns 4 otherwise. * \returns 4 otherwise.
*/ */
int buffer_get_u32(BUFFER *buffer, u32 *data){ int buffer_get_u32(struct buffer_struct *buffer, u32 *data){
return buffer_get_data(buffer,data,sizeof(u32)); return buffer_get_data(buffer,data,sizeof(u32));
} }
/** \internal /** \internal
@@ -268,7 +321,7 @@ int buffer_get_u32(BUFFER *buffer, u32 *data){
* \returns 0 if there is not enough data in buffer * \returns 0 if there is not enough data in buffer
* \returns 8 otherwise. * \returns 8 otherwise.
*/ */
int buffer_get_u64(BUFFER *buffer, u64 *data){ int buffer_get_u64(struct buffer_struct *buffer, u64 *data){
return buffer_get_data(buffer,data,sizeof(u64)); return buffer_get_data(buffer,data,sizeof(u64));
} }
/** \internal /** \internal
@@ -277,23 +330,30 @@ int buffer_get_u64(BUFFER *buffer, u64 *data){
* \returns The SSH String read * \returns The SSH String read
* \returns NULL otherwise. * \returns NULL otherwise.
*/ */
STRING *buffer_get_ssh_string(BUFFER *buffer){ struct string_struct *buffer_get_ssh_string(struct buffer_struct *buffer) {
u32 stringlen; u32 stringlen;
u32 hostlen; u32 hostlen;
STRING *str; struct string_struct *str = NULL;
if(buffer_get_u32(buffer,&stringlen)==0)
return NULL; if (buffer_get_u32(buffer, &stringlen) == 0) {
hostlen=ntohl(stringlen); return NULL;
/* verify if there is enough space in buffer to get it */ }
if(buffer->pos+hostlen>buffer->used) hostlen = ntohl(stringlen);
return NULL; /* it is indeed */ /* verify if there is enough space in buffer to get it */
str=string_new(hostlen); if ((buffer->pos + hostlen) > buffer->used) {
if(buffer_get_data(buffer,str->string,hostlen)!=hostlen){ return NULL; /* it is indeed */
// should never happen }
free(str); str = string_new(hostlen);
return NULL; if (str == NULL) {
} return NULL;
return str; }
if (buffer_get_data(buffer, str->string, hostlen) != hostlen) {
/* should never happen */
SAFE_FREE(str);
return NULL;
}
return str;
} }
/** \internal /** \internal
* \brief gets a mpint out of the buffer. Adjusts the read pointer. * \brief gets a mpint out of the buffer. Adjusts the read pointer.
@@ -303,22 +363,28 @@ STRING *buffer_get_ssh_string(BUFFER *buffer){
* \returns NULL otherwise * \returns NULL otherwise
*/ */
STRING *buffer_get_mpint(BUFFER *buffer){ struct string_struct *buffer_get_mpint(struct buffer_struct *buffer) {
u16 bits; u16 bits;
u32 len; u32 len;
STRING *str; struct string_struct *str = NULL;
if(buffer_get_data(buffer,&bits,sizeof(u16))!= sizeof(u16))
return NULL; if (buffer_get_data(buffer, &bits, sizeof(u16)) != sizeof(u16)) {
bits=ntohs(bits); return NULL;
len=(bits+7)/8; }
if(buffer->pos+len > buffer->used) bits = ntohs(bits);
return NULL; len = (bits + 7) / 8;
str=string_new(len); if ((buffer->pos + len) > buffer->used) {
if(buffer_get_data(buffer,str->string,len)!=len){ return NULL;
free(str); }
return NULL; str = string_new(len);
} if (str == NULL) {
return str; return NULL;
}
if (buffer_get_data(buffer, str->string, len) != len) {
SAFE_FREE(str);
return NULL;
}
return str;
} }
/** @} */ /** @} */