Memory error in HBSSL contrib (HB_SSL_READ_LINE)

59 views
Skip to first unread message

tomalla5120x

unread,
Jan 9, 2026, 5:28:35 PM (4 days ago) Jan 9
to Harbour Developers
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])

And indeed the source of the problem is in the HB_SSL_READ_LINE ( https://github.com/harbour/core/blob/7c7d7d67cefc52cf9706d370186423de45980a45/contrib/hbssl/ssl_hb.c#L172 ). Here's the shortened snippet of the function:

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
Reply all
Reply to author
Forward
0 new messages