[Previous entry: "Are you sure? Surety, integrity, confidentiality and availability"] [Next entry: "Code Commandos, SDL and Metrics"]
04/15/2008: "A bug in fread() could lead to a buffer overflow vulnerability"
Back in October 2005 I isolated a bug in the MS C runtime fread() function which in certain cirumstances could lead to a buffer overflow. When a file is opened in text mode any carriage-returns/line-feeds (CR-LFs) are converted to CR. This is documented on MSDN. However, if the destination buffer for fread is bigger than 4095 bytes then the translation takes place in place and for each CRLF the buffer is shifted left once. Once all CR-LFs are converted no NULL terminator is set. So if a text file has the following contents
"16*CRLF"0123456789ABCDEF
what ends up in the destination buffer is
"16*CR"0123456789ABCDEF0123456789ABCDEF
However the return value for fread is 32. This can lead to an overflow - consider the following code:
#include "stdio.h"
FILE *fd =NULL;
char *buffer = NULL;
int main()
{
unsigned int bytesread = 0;
unsigned char name[36]="";
buffer = (char *) malloc(4100);
if(!buffer)
return 0;
memset(buffer,0,4100);
fd = fopen("foo.txt","r");
if(!fd)
{
free(buffer);
return 0;
}
bytesread = fread(buffer,1,4096,fd);
printf("Bytes read = %d\n",bytesread);
// check that there are no more than 32 bytes in the buffer
if(bytesread > 32)
{
free(buffer);
fclose(fd);
printf("Name is too long\n");
return 1;
}
strcpy(name,buffer);
printf("%s\n",name);
free(buffer);
fclose(fd);
return 0;
}
Also, if 0x1A (Ctrl^Z) is encountered then fread returns the number of bytes up to 0x1A even though the number of bytes in the buffer is longer.
Now this is not going to turn into a class of flaw like format string bugs or anything, of course, but the lessson here is don't trust the return value of fread() as you could end up in trouble!