Commit 8f0f1635 authored by Simon Morlat's avatar Simon Morlat

fix many buffer overflows again (previous attempt was not sufficent)

parent 376409db
This diff is collapsed.
......@@ -127,7 +127,7 @@ int belle_sip_header_address_marshal(belle_sip_header_address_t* header, char* b
current_offset+=belle_sip_parameters_marshal(&header->base,buff,current_offset,buff_size);
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_address,parameters,"header_address")
......@@ -184,7 +184,7 @@ int belle_sip_header_allow_marshal(belle_sip_header_allow_t* allow, char* buff,u
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",allow->method);
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_allow,header,"Allow")
......@@ -222,7 +222,7 @@ int belle_sip_header_contact_marshal(belle_sip_header_contact_t* contact, char*
}
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_contact,header_address,BELLE_SIP_CONTACT)
BELLE_SIP_PARSE(header_contact)
......@@ -275,7 +275,7 @@ unsigned int belle_sip_header_contact_not_equals(const belle_sip_header_contact_
current_offset+=belle_sip_header_address_marshal(&header->address, buff,current_offset, buff_size); \
if (current_offset>=buff_size) goto end;\
end:\
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
struct _belle_sip_header_from {
belle_sip_header_address_t address;
......@@ -409,7 +409,7 @@ int belle_sip_header_user_agent_marshal(belle_sip_header_user_agent_t* user_agen
if (current_offset>=buff_size) goto end;
}
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_user_agent,header,"User-Agent")
......@@ -504,7 +504,7 @@ int belle_sip_header_via_marshal(belle_sip_header_via_t* via, char* buff,unsigne
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
belle_sip_header_via_t* belle_sip_header_via_create(const char *host, int port, const char *transport, const char *branch){
......@@ -604,7 +604,7 @@ int belle_sip_header_call_id_marshal(belle_sip_header_call_id_t* call_id, char*
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",call_id->call_id);
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
unsigned int belle_sip_header_call_id_equals(const belle_sip_header_call_id_t* a,const belle_sip_header_call_id_t* b) {
return strcasecmp(a->call_id,b->call_id) == 0;
......@@ -637,7 +637,7 @@ int belle_sip_header_cseq_marshal(belle_sip_header_cseq_t* cseq, char* buff,unsi
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%i %s",cseq->seq_number,cseq->method);
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
belle_sip_header_cseq_t * belle_sip_header_cseq_create(unsigned int number, const char *method){
belle_sip_header_cseq_t *cseq=belle_sip_header_cseq_new();
......@@ -678,7 +678,7 @@ int belle_sip_header_content_type_marshal(belle_sip_header_content_type_t* conte
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_content_type,parameters,BELLE_SIP_CONTENT_TYPE)
BELLE_SIP_PARSE(header_content_type)
......@@ -776,7 +776,7 @@ int belle_sip_header_content_length_marshal(belle_sip_header_content_length_t* c
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%i",content_length->content_length);
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_content_length,header,BELLE_SIP_CONTENT_LENGTH)
BELLE_SIP_PARSE(header_content_length)
......@@ -811,7 +811,7 @@ int belle_sip_header_expires_marshal(belle_sip_header_expires_t* expires, char*
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%i",expires->expires);
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_expires,header,BELLE_SIP_EXPIRES)
BELLE_SIP_PARSE(header_expires)
......@@ -844,7 +844,7 @@ int belle_sip_header_extension_marshal(belle_sip_header_extension_t* extension,
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",extension->value);
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_extension,header,NULL)
......@@ -1045,7 +1045,7 @@ int belle_sip_header_authorization_marshal(belle_sip_header_authorization_t* aut
if (current_offset>=buff_size) goto end;
}
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_authorization,parameters,BELLE_SIP_AUTHORIZATION)
BELLE_SIP_PARSE(header_authorization)
......@@ -1143,7 +1143,7 @@ int belle_sip_header_www_authenticate_marshal(belle_sip_header_www_authenticate_
border=", ";
}
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
#define SET_ADD_STRING_LIST(header,name) \
void header##_set_##name(header##_t* obj, belle_sip_list_t* value) {\
......@@ -1219,7 +1219,7 @@ int belle_sip_header_max_forwards_marshal(belle_sip_header_max_forwards_t* max_f
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%i",max_forwards->max_forwards);
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_max_forwards,header,"Max-Forwards")
BELLE_SIP_PARSE(header_max_forwards)
......@@ -1254,7 +1254,7 @@ int belle_sip_header_subscription_state_marshal(belle_sip_header_subscription_st
current_offset+=belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(subscription_state), buff,current_offset, buff_size);
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_subscription_state,parameters,BELLE_SIP_SUBSCRIPTION_STATE)
BELLE_SIP_PARSE(header_subscription_state)
......@@ -1329,7 +1329,7 @@ int belle_sip_header_replaces_marshal(belle_sip_header_replaces_t* replaces, cha
current_offset+=belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(replaces), buff,current_offset, buff_size);
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_replaces,parameters,BELLE_SIP_REPLACES)
BELLE_SIP_PARSE(header_replaces)
......@@ -1401,7 +1401,7 @@ int belle_sip_header_date_marshal(belle_sip_header_date_t* obj, char* buff,unsig
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",obj->date);
if (current_offset>=buff_size) goto end;
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW_HEADER(header_date,header,BELLE_SIP_DATE)
......
......@@ -259,11 +259,46 @@ const char* belle_sip_object_get_name(belle_sip_object_t* object) {
return object->name;
}
/*turn this to 1 if you feel a marshal method is buggy.*/
#define CHECKED_MARSHAL 0
#if CHECKED_MARSHAL
static int checked_marshal(belle_sip_object_vptr_t *vptr, belle_sip_object_t* obj, char* buff,unsigned int offset,size_t buff_size){
int tmp_buf_size=buff_size*2;
char *p=(char*)belle_sip_malloc0(tmp_buf_size);
int i;
int ret=vptr->marshal(obj,p,offset,buff_size);
int written;
for (i=offset;i<buff_size;++i){
if (p[i]=='\0') break;
}
written=i-offset;
if (written>(buff_size-offset)){
belle_sip_fatal("Object of type %s commited a buffer overflow by marshalling %i bytes ",
vptr->type_name,written);
}
if (written!=ret && written!=(buff_size-offset-1)){ /*this is because snprintf won't allow you to write a non null character at the end of the buffer*/
belle_sip_fatal("Object of type %s marshalled %i bytes but said it marshalled %i bytes !",
vptr->type_name,written,ret);
}
memcpy(buff+offset,p+offset,ret);
belle_sip_free(p);
return ret;
}
#endif
int belle_sip_object_marshal(belle_sip_object_t* obj, char* buff,unsigned int offset,size_t buff_size) {
belle_sip_object_vptr_t *vptr=obj->vptr;
while (vptr != NULL) {
if (vptr->marshal != NULL) {
#if CHECKED_MARSHAL
return checked_marshal(vptr,obj,buff,offset,buff_size);
#else
return vptr->marshal(obj,buff,offset,buff_size);
#endif
} else {
vptr=vptr->parent;
}
......@@ -286,6 +321,12 @@ static char * belle_sip_object_to_alloc_string(belle_sip_object_t *obj, int size
return buf;
}
static int get_hint_size(int size){
if (size<128)
return 128;
return size;
}
char* belle_sip_object_to_string(void* _obj) {
belle_sip_object_t *obj=BELLE_SIP_OBJECT(_obj);
if (obj->vptr->tostring_bufsize_hint!=0){
......@@ -295,10 +336,10 @@ char* belle_sip_object_to_string(void* _obj) {
int size = belle_sip_object_marshal(obj,buff,0,sizeof(buff));
if (size>=sizeof(buff)-1){
belle_sip_message("belle_sip_object_to_string(): temporary buffer is too short while doing to_string() for %s, retrying", obj->vptr->type_name);
return belle_sip_object_to_alloc_string(obj,2*size);
return belle_sip_object_to_alloc_string(obj,get_hint_size(2*size));
}
buff[size]='\0';
obj->vptr->tostring_bufsize_hint=2*size;
obj->vptr->tostring_bufsize_hint=get_hint_size(2*size);
return belle_sip_strdup(buff);
}
}
......
......@@ -51,9 +51,8 @@ int belle_sip_parameters_marshal(const belle_sip_parameters_t* params, char* buf
} else {
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,";%s",container->name);
}
if (current_offset>=buff_size) goto end;
if (current_offset>=buff_size) return buff_size-offset;
}
end:
return current_offset-offset;
}
BELLE_SIP_NEW_HEADER(parameters,header,"parameters")
......
......@@ -74,13 +74,13 @@ int belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buff,unsigned int of
const belle_sip_list_t* list=belle_sip_parameters_get_parameters(uri->header_list);
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s:",uri->secure?"sips":"sip");
if (current_offset>=buff_size) goto end;
if (current_offset>=buff_size) return buff_size-offset;
if (uri->user) {
char* escaped_username=belle_sip_to_escaped_string(uri->user);
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s@",escaped_username);
belle_sip_free(escaped_username);
if (current_offset>=buff_size) goto end;
if (current_offset>=buff_size) return buff_size-offset;
}
if (uri->host) {
if (strchr(uri->host,':')) { /*ipv6*/
......@@ -88,16 +88,16 @@ int belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buff,unsigned int of
} else {
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",uri->host);
}
if (current_offset>=buff_size) goto end;
if (current_offset>=buff_size) return buff_size-offset;
} else {
belle_sip_warning("no host found in this uri");
}
if (uri->port>0) {
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,":%i",uri->port);
if (current_offset>=buff_size) goto end;
if (current_offset>=buff_size) return buff_size-offset;
}
current_offset+=belle_sip_parameters_marshal(&uri->params,buff,current_offset,buff_size);
if (current_offset>=buff_size) goto end;
if (current_offset>=buff_size) return buff_size-offset;
for(;list!=NULL;list=list->next){
belle_sip_param_pair_t* container = list->data;
......@@ -108,9 +108,8 @@ int belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buff,unsigned int of
//subsequent headers
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"&%s=%s",container->name,container->value);
}
if (current_offset>=buff_size) goto end;
if (current_offset>=buff_size) return buff_size-offset;
}
end:
return current_offset-offset;
}
......
......@@ -255,15 +255,13 @@ int belle_sip_headers_marshal(belle_sip_message_t *message, char* buff,unsigned
;header_list=header_list->next) {
belle_sip_header_t *h=BELLE_SIP_HEADER(header_list->data);
current_offset+=belle_sip_object_marshal(BELLE_SIP_OBJECT(h),buff,current_offset,buff_size);
if (current_offset>=buff_size) goto end;
if (current_offset>=buff_size) return buff_size-offset;
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s","\r\n");
if (current_offset>=buff_size) goto end;
if (current_offset>=buff_size) return buff_size-offset;
}
}
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s","\r\n");
if (current_offset>=buff_size) goto end;
end:
if (current_offset>=buff_size) return buff_size-offset;
return current_offset-offset;
}
......@@ -301,7 +299,7 @@ int belle_sip_request_marshal(belle_sip_request_t* request, char* buff,unsigned
if (current_offset>=buff_size) goto end;
}
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW(request,message)
......@@ -483,7 +481,7 @@ int belle_sip_response_marshal(belle_sip_response_t *resp, char* buff,unsigned i
if (current_offset>=buff_size) goto end;
}
end:
return current_offset-offset;
return MIN(current_offset-offset,buff_size-offset);
}
BELLE_SIP_NEW(response,message);
BELLE_SIP_PARSE(response)
......
......@@ -313,8 +313,7 @@ static void test_simple_session_description(void) {
return;
}
static void test_session_description(void) {
const char* l_src = "v=0\r\n"\
static const char* big_sdp = "v=0\r\n"\
"o=jehan-mac 1239 1239 IN IP6 2a01:e35:1387:1020:6233:4bff:fe0b:5663\r\n"\
"s=SIP Talk\r\n"\
"c=IN IP4 192.168.0.18\r\n"\
......@@ -336,6 +335,9 @@ static void test_session_description(void) {
"a=rtpmap:97 theora/90000\r\n"\
"a=rtpmap:98 H263-1998/90000\r\n"\
"a=fmtp:98 CIF=1;QCIF=1\r\n";
static void test_session_description(void) {
const char* l_src = big_sdp;
belle_sdp_origin_t* l_origin;
belle_sdp_session_description_t* lTmp;
belle_sip_list_t* media_descriptions;
......@@ -377,6 +379,31 @@ static void test_session_description(void) {
return;
}
static void test_overflow(void){
belle_sdp_session_description_t* sdp;
belle_sip_list_t *mds;
belle_sdp_media_description_t *vmd;
int i;
const int buffsize=1024;
char *buffer=belle_sip_malloc0(buffsize);
int err;
sdp=belle_sdp_session_description_parse(big_sdp);
CU_ASSERT_PTR_NOT_NULL(sdp);
mds=belle_sdp_session_description_get_media_descriptions(sdp);
CU_ASSERT_PTR_NOT_NULL(mds);
CU_ASSERT_PTR_NOT_NULL(mds->next);
vmd=(belle_sdp_media_description_t*)mds->next->data;
for(i=0;i<16;i++){
belle_sdp_media_description_add_attribute(vmd,belle_sdp_attribute_create("candidate","2 1 UDP 1694498815 82.65.223.97 9078 typ srflx raddr 192.168.0.2 rport 9078"));
}
err=belle_sip_object_marshal(BELLE_SIP_OBJECT(sdp),buffer,0,buffsize);
belle_sip_message("marshal size is %i",err);
CU_ASSERT_TRUE(err==buffsize);
belle_sip_object_unref(sdp);
belle_sip_free(buffer);
}
static belle_sdp_mime_parameter_t* find_mime_parameter(belle_sip_list_t* list,const int format) {
for(;list!=NULL;list=list->next){
if (belle_sdp_mime_parameter_get_media_format((belle_sdp_mime_parameter_t*)list->data) == format) {
......@@ -485,7 +512,8 @@ test_t sdp_tests[] = {
{ "mime parameter", test_mime_parameter },
{ "Media description", test_media_description },
{ "Simple session description", test_simple_session_description },
{ "Session description", test_session_description }
{ "Session description", test_session_description },
{ "Marshal buffer overflow", test_overflow }
};
test_suite_t sdp_test_suite = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment