Fix issue in richio.cpp, when printing strings with a size > 500 chars.
This was due to an use of twice the same va_list by 2 calls to vsnprintf, but the first call can change the va_list.
This commit is contained in:
parent
a8bffb862c
commit
a928bbfaac
|
@ -3,7 +3,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2007-2011 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
|
||||
* Copyright (C) 2007 KiCad Developers, see change_log.txt for contributors.
|
||||
* Copyright (C) 2015 KiCad Developers, see change_log.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -43,6 +43,14 @@
|
|||
static int vprint( std::string* result, const char* format, va_list ap )
|
||||
{
|
||||
char msg[512];
|
||||
// This function can call vsnprintf twice.
|
||||
// But internally, vsnprintf retrieves arguments from the va_list identified by arg as if
|
||||
// va_arg was used on it, and thus the state of the va_list is likely to be altered by the call.
|
||||
// see: www.cplusplus.com/reference/cstdio/vsnprintf
|
||||
// we make a copy of va_list ap for the second call, if happens
|
||||
va_list tmp;
|
||||
va_copy( tmp, ap );
|
||||
|
||||
size_t len = vsnprintf( msg, sizeof(msg), format, ap );
|
||||
|
||||
if( len < sizeof(msg) ) // the output fit into msg
|
||||
|
@ -58,11 +66,13 @@ static int vprint( std::string* result, const char* format, va_list ap )
|
|||
|
||||
buf.reserve( len+1 ); // reserve(), not resize() which writes. +1 for trailing nul.
|
||||
|
||||
len = vsnprintf( &buf[0], len+1, format, ap );
|
||||
len = vsnprintf( &buf[0], len+1, format, tmp );
|
||||
|
||||
result->append( &buf[0], &buf[0] + len );
|
||||
}
|
||||
|
||||
va_end( tmp ); // Release the temporary va_list, initialised from ap
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -397,13 +407,23 @@ const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee )
|
|||
|
||||
int OUTPUTFORMATTER::vprint( const char* fmt, va_list ap ) throw( IO_ERROR )
|
||||
{
|
||||
// This function can call vsnprintf twice.
|
||||
// But internally, vsnprintf retrieves arguments from the va_list identified by arg as if
|
||||
// va_arg was used on it, and thus the state of the va_list is likely to be altered by the call.
|
||||
// see: www.cplusplus.com/reference/cstdio/vsnprintf
|
||||
// we make a copy of va_list ap for the second call, if happens
|
||||
va_list tmp;
|
||||
va_copy( tmp, ap );
|
||||
int ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
|
||||
|
||||
if( ret >= (int) buffer.size() )
|
||||
{
|
||||
buffer.resize( ret + 2000 );
|
||||
ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
|
||||
buffer.resize( ret + 1000 );
|
||||
ret = vsnprintf( &buffer[0], buffer.size(), fmt, tmp );
|
||||
}
|
||||
|
||||
va_end( tmp ); // Release the temporary va_list, initialised from ap
|
||||
|
||||
if( ret > 0 )
|
||||
write( &buffer[0], ret );
|
||||
|
||||
|
|
Loading…
Reference in New Issue