I got a problem when reading SSL response that causes a segmentation fault. I read the response into a buffer, then append it to a malloced string and memory reset it to 0 till the response is fully read, but when I try this in a multi threaded program, after some operations it gives me segmentation fault. When I remove strcat
it doesn't give me segmentation fault even if I run it for hours.
Example:
char* response = malloc(10000);
char buffer[10000] = { 0 };
while(SSL_read(ssl,buf,sizeof(buffer)) > 0){
strcat(response,buffer);
memset(buffer,0,sizeof(buffer));
}
Errors
free(): invalid next size (normal)
malloc_consolidate(): invalid chunk
I made sure of freeing both of SSL and CTX and close socket and free the malloced string.
CodePudding user response:
There are a few problems with your code:
You are not dealing with C strings, you are dealing with arbitrary byte sequences.
SSL_read()
reads bytes, not C strings, and you cannot treat them as strings. What you read cannot be assumed to be NUL-terminated (\0
), therefore you cannot usestrcat
,strlen
or other similar functions that operate on strings.You are reading data continuously in a loop into a fixed size buffer. Your code will overflow the destination buffer (
response
) very easily.Not an error, but there isn't really any need for an intermediate buffer to begin with. Why waste time copying stuff around two times (one with
SSL_read()
and one withstrcat
)? Just read directly intoresponse
. On top of that, thememset()
to clear the contents ofbuffer
is also unneeded. Overall you are scanning 3 times over the same buffer while you could simply do that once.Again, not an error, but
SSL_read()
returnsint
and uses that to return the read size. You would be much better off usingsize_t
to avoid unwanted problems with signed math and possible overflows. You can useSSL_read_ex()
for this purpose.
Here's a snippet of code that does what you want in a more robust way:
#define CHUNK_SIZE 10000
unsigned char *response = NULL;
size_t size = 0;
size_t space_left = 0;
size_t total_read = 0;
size_t n;
while (1) {
// Allocate more memory if needed.
if (space_left < CHUNK_SIZE) {
unsigned char *tmp = realloc(response, size CHUNK_SIZE);
if (!tmp) {
// Handle realloc error
break;
}
response = tmp;
size = CHUNK_SIZE;
}
if (SSL_read_ex(ssl, response total_read, space_left, &n)) {
total_read = n;
space_left -= n;
} else {
// Handle error
break;
}
}
CodePudding user response:
You never initialized response()
. The arguments to strcat()
have to be null-terminated strings.
You should also subtract 1 from the size of the buffer when calling SSL_read()
, to ensure there will always be room for its null terminator.
char* response = malloc(10000);
response[0] = '\0';
char buffer[10000] = { 0 };
while(SSL_read(ssl,buf,sizeof(buffer)-1) > 0){
strcat(response,buffer);
memset(buffer,0,sizeof(buffer));
}