String::vprintf has problems on 64-bit Linux


#1

The implementation of “String::vprintf” has problems with strings larger than 256 characters on 64-bit Linux:
If you try to format a string with “String::vprintf” that results in more than 256 characters, that gives wrong results or even crashes on Linux 64-bit. As I investigated it, this happens because it calls “CharacterFunctions::vprintf” (which itself calls “vswprintf”) more than one time with growing buffer sizes. But obviously “vswprintf” on 64-bit Linux changes the va_list argument in some way, also if the call fails because the buffer is to small. So in the next call it uses wrong arguments, and if the call finally succeeds, you get some undefined results for the formatted arguments.

The following change to “String::vprintf” solves that issue. Since it is only reproduceable in 64-bit Linux, I changed it only for that platform:

void String::vprintf (const tchar* const pf, va_list& args) throw()
{
    tchar stackBuf [256];
    unsigned int bufSize = 256;
    tchar* buf = stackBuf;

    deleteInternal();

    for (;;)
    {
#if JUCE_LINUX && JUCE_64BIT
        va_list tmpArgs;
        va_copy(tmpArgs, args);
        const int num = CharacterFunctions::vprintf (buf, bufSize - 1, pf, tmpArgs);
        va_end(tmpArgs);
#else
        const int num = CharacterFunctions::vprintf (buf, bufSize - 1, pf, args);
#endif

        if (num > 0)
        {
....

Andreas


#2

ah - excellent stuff, thanks.

I wonder why 64-bit seems to break so much seemingly-unrelated bits of code…