My application using the HBSSL contrib crashed recently - the free() function from libc reported an error: "free(): invalid next size (fast): ...". Obviously the memory was corrupted.
I've run valgrind to diagnose the problem. Here's the listing:
==14261== Invalid write of size 1
==14261== at [redacted]: hb_itemPutCLPtr (in [redacted])
==14261== by [redacted]: hb_storclen_buffer (in [redacted])
==14261== by [redacted]: HB_FUN_HB_SSL_READ_LINE (in [redacted])
==14261== by [redacted]: hb_vmProc (in [redacted])
==14261== by [redacted]: hb_vmExecute (in [redacted])
...
==14261== by [redacted]: hb_vmExecute (in [redacted])
==14261== by [redacted]: hb_vmProc (in [redacted])
==14261== by [redacted]: main (in [redacted])
==14261== Address [redacted] is 0 bytes after a block of size 88 alloc'd
==14261== at [redacted]: malloc (vg_replace_malloc.c:299)
==14261== by [redacted]: hb_xrealloc (in [redacted])
==14261== by [redacted]: HB_FUN_HB_SSL_READ_LINE (in [redacted])
==14261== by [redacted]: hb_vmProc (in [redacted])
==14261== by [redacted]: hb_vmExecute (in [redacted])
...
==14261== by [redacted]: hb_vmExecute (in [redacted])
==14261== by [redacted]: hb_vmProc (in [redacted])
==14261== by [redacted]: main (in [redacted])
HB_FUNC( HB_SSL_READ_LINE )
{
// ...
int iPos = 0;
int iAllocated = 0;
char * retval = NULL;
for( ;; )
{
char buffer[ 1 ];
int iLen;
// ... read the character into buffer[0]
if( iPos == iAllocated )
{
iAllocated += iBufferSize;
retval = ( char * ) hb_xrealloc( retval, iAllocated );
}
retval[ iPos++ ] = buffer[ 0 ];
// ...
}
if( retval )
{
if( ! hb_storclen_buffer( retval, iPos, 2 ) )
hb_xfree( retval );
}
else
hb_storc( NULL, 2 );
hb_retni( iPos );
}
}
else
hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
}
The hb_xrealloc function allocates the memory for the entire buffer, including the terminating null. The hb_storclen_buffer function however expects the passed length to be the length of the actual string (i.e. without the null character).
Let's assume: iPos = 79, iAllocated = 80. We read the next byte into retval[79] and increment iPos to 80. Then we call de facto hb_storclen_buffer(retval, 80, 2). As a result the nested hb_itemPutCLPtr call is saving the '\0' character at the retval[80], which exceeds the allocated buffer.
Can I expect a fix solving the at any point in the future? Either way I'll have to patch it locally in my Harbour installation and recompile the project until the issue is resolved oficially.
Tom