Thread: Hit a bug with my custom printf implementation...

  1. #1
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733

    Hit a bug with my custom printf implementation...

    Getting a segfault that I'm struggling to identify the root cause of, the surface cause is that the object pointer is empty but the root cause for why that object was empty when it should've had a value is currently beyond me, if anyone's able to spot it from the below code &/or the link I'd appreciate the help.

    Here's a copy of the main function with a comment added to the line that segfaults:
    Code:
    PAW_API pawd	pawInitStringv( PAWS *str, pawhhs args, va_list va )
    {
    	pawd const buf_opts = PAW_O_CLEAR_NEW | PAW_O_ZERO_TAIL;
    	pawd need = 0, ate = 0, pos = 0, end = 0, max = 0;
    	pawd j, leng = pawhhs_length(args);
    	PAWVA_UDV UDV = {0};
    	PAWBUF *Cfgs = &(UDV.Cfgs);
    	PAWBUF *Rdio = &(UDV.Rdio);
    	PAWVA_RDIO *rdio = NULL;
    	PAWVA_PUTF *putf = NULL;
    	PAWVA_DATA *data = NULL;
    
    	UDV.args = args;
    	UDV.options	= pawStdOptions;
    	UDV.scalers	= pawStdScalers;
    	UDV.formats	= pawStdFormats;
    
    	if ( leng <= 0 )
    		return -(leng < 0);
    
    	rdio = pawInitBuffert( Rdio, sizeof(PAWVA_RDIO), buf_opts, leng );
    
    	for ( UDV.i = 0; args[end]; UDV.i = end )
    	{
    		pawhhc c = args[end], n = args[++end];
    		if ( c != '%' )
    			continue;
    
    		/* Should we include % character in snippet? */
    		end += (n == '%' || !n);
    		/* Append snippet to list for adding later */
    		j = Rdio->count;
    		join_read_string( &UDV, pos, end++ );
    		rdio = pawSeekBufferi( Rdio, j );
    
    		if ( !n || n == '%' || n == '@' || n == '>' )
    		{
    			pos = end + 1;
    			/* Have we escaped a % character? */
    			switch ( n )
    			{
    			case '%': case 0:
    				rdio->end++;
    				rdio->len++;
    				break;
    			/* Are we taking a new list of options? */
    			case '<':
    				UDV.options = va_arg( va, pawva_flag_cb* );
    				break;
    			/* Are we taking a new list of scalers? */
    			case '@':
    				UDV.scalers = va_arg( va, PAWVA_MODF* );
    				break;
    			/* Are we taking a new list of formats? */
    			case '>':
    				UDV.formats = va_arg( va, PAWVA_PUTF** );
    				break;
    			}
    
    			continue;
    		}
    
    		for ( j = 0; joinCBs[j]; ++j )
    		{
    			ate = joinCBs[j]( &UDV, pos, end );
    			if ( ate < 0 )
    			{
    				pawTermBuffer( Rdio );
    				return -1;
    			}
    			pos = end + ate;
    		}
    	}
    
    	/* Collect remaining text */
    	join_read_string( &UDV, pos, end );
    
    	rdio = pawSeekBufferHead( Rdio );
    	for ( j = 0; j < Rdio->count; ++j, ++rdio )
    	{
    		if ( rdio->get > max )
    			max = rdio->get;
    	}
    
    	max += sizeof(PAWVA_DATA);
    	/* Work out how many potential characters are needed */
    	data = pawInitBuffert( Cfgs, max, buf_opts, Rdio->count );
    
    	need	= 0;
    	if ( !data )
    		ate = -1;
    	else
    	{
    		pawd cfg = 0;
    		rdio = pawSeekBufferHead( Rdio );
    		data = pawGrowBufferc( Cfgs, 1 );
    		data->cfg = data + 1;
    
    		for ( j = 0; j < Rdio->count; ++j, ++rdio )
    		{
    			rdio->data = data;
    			ate = rdio->readCB( rdio, va );
    			if ( ate < 0 )
    				break;
    
    			need += ate;
    			if ( rdio->putf )
    			{
    				(void)pawGrowBufferc( Cfgs, ++cfg + 1 );
    				data = pawSeekBufferi( Cfgs, cfg );
    				data->cfg = data + 1;
    			}
    		}
    
    		/* Allocate needed memory and start printing the value to the
    		 * buffer */
    		ate = -(ate < 0 || !pawInitStringt( str, need ));
    		for ( cfg = 0; cfg < Cfgs->count; ++cfg )
    		{
    			data = pawSeekBufferi( Cfgs, cfg );
    			putf = data->cb.putf;
    
    			if ( ate >= 0 )
    				ate = putf->join( data, str ); // Segfault occurs here on pawInitStringf( &strbuf, "%u", 10 ) with 3 configs in buffer, should only be 1 config and it should've had the putf member filled by this point
    
    			if ( putf->term && data->cfg )
    				putf->term( data->cfg );
    		}
    
    		if ( ate < 0 )
    		{
    			PAW_BREAK;
    			pawTermString( str );
    		}
    		else
    		{
    			/* release unneeded memory */
    			pawTrimBufferc( str, str->count );
    		}
    	}
    
    	pawTermBuffer( Cfgs );
    	pawTermBuffer( Rdio );
    	return (ate < 0) ? -1 : str->count;
    }
    Next a link for related code:
    src/libpaw/global/strbuf.c * 508534bdf007e5b7278aa29ac329e4ec74eb7138 * Lee Shallis / Dragonbuilder * GitLab

    The above function is at the bottom of the file.

  2. #2
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Never mind, it was because I was incrementing end in the wrong place at the top of the 1st loop, adding braces to the continue statement below it and shifting the increment to there and putting "end + 1" where the increment was resolved the issue.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Custom printf/scanf suggestions desired
    By awsdert in forum C Programming
    Replies: 1
    Last Post: 05-29-2022, 01:03 AM
  2. Replies: 7
    Last Post: 10-01-2008, 07:45 PM
  3. make printf using printf?
    By germaneater in forum C Programming
    Replies: 9
    Last Post: 11-10-2004, 10:58 PM
  4. Custom UI
    By cfrost in forum Windows Programming
    Replies: 5
    Last Post: 08-20-2004, 12:52 PM

Tags for this Thread