Home > Software engineering >  Why doesn't _ui64tow_s work when _ui64tow does?
Why doesn't _ui64tow_s work when _ui64tow does?

Time:07-10

I wrote some code which uses the _ui64tow function, but I'd like to use _ui64tow_s, which is safer. Unfortunately, it seems I can't get it to work properly.

Here's the original code:

#define PERCENT_SHIFT       10000000
#define SHORTSTRLEN         32

TCHAR   g_szZero[SHORTSTRLEN]   = TEXT("0");
WCHAR* PerfGraph::FloatToString(ULONGLONG ullValue, WCHAR* psz, BOOLEAN bDisplayDec)
{
    ULONGLONG ulDecimal = 0;
    ULONGLONG ulNumber = 0;
    WCHAR wsz[100];

    // Get the integer value of the number:

    ulNumber = ullValue / PERCENT_SHIFT;

    // BUGBUG: please note that _ui64tow is unsafe.

    if (_ui64tow(ulNumber, wsz, 10))
    {
        lstrcpy(psz, wsz);
        if (ulNumber)
        {
            ullValue = ullValue - ulNumber * PERCENT_SHIFT;
        }
        if (!ulNumber || bDisplayDec)
        {
            ulDecimal = ullValue * 100 / PERCENT_SHIFT;
            if (ulDecimal && _ui64tow(ulDecimal, wsz, 10))
            {
                lstrcat(psz, g_szDecimal);
                if (ulDecimal < 10) lstrcat(psz, g_szZero);
                if (wsz[1] == L'0') wsz[1] = L'\0';
                lstrcat(psz, wsz);
            }
        }
    }

    return psz;
}

And here's what I tried (please refer to the above code):

if (_ui64tow_s(ulNumber, wsz, sizeof(wsz) / sizeof WCHAR, 10))

and:

if (ulDecimal && _ui64tow(ulDecimal, wsz, sizeof(wsz) / sizeof WCHAR, 10))

What am I doing wrong?

CodePudding user response:

The _ui64tow_s function returns an error_t value which is zero on success (unlike the plain _ui64tow function, which returns a copy of the string pointer argument).

So, when changing from using _ui64tow to using _ui64tow_s, you must check against zero for success, typically by adding the ! operator to the (returned value of the) function call.

Thus, your calls should be made in the if statements like this:

    if (!_ui64tow_s(ulNumber, wsz, sizeof(wsz) / sizeof(WCHAR), 10))
    //  ^ Note the added "!"
    {
        lstrcpy(psz, wsz);
        if (ulNumber)
        {
            ullValue = ullValue - ulNumber * PERCENT_SHIFT;
        }
        if (!ulNumber || bDisplayDec)
        {
            ulDecimal = ullValue * 100 / PERCENT_SHIFT;
            if (ulDecimal && !_ui64tow_s(ulDecimal, wsz, sizeof(wsz) / sizeof(WCHAR), 10))
                      // ... ^ and another "!" here
            {
                lstrcat(psz, g_szDecimal);
                if (ulDecimal < 10) lstrcat(psz, g_szZero);
                if (wsz[1] == L'0') wsz[1] = L'\0';
                lstrcat(psz, wsz);
            }
        }
    }
  • Related