Heap corruption after second use of strcat

Viewed 87

This is driving me nuts because I'm not seeing what bonehead mistake I'm making here.

In the following snippet (note this is just a test snippet is from a larger method), I'm basically just attempting to copy a string that's retrieved from a SQL method, and then if the user specifies in the method an additional number of columns, append a delimiter (in this case a semi-colon) and the additional string:

//...
char** pLocalArray;
char buff[512];
//... pLocalArray is allocated

// The semicolon is replaced by a variable passed into the function, but just putting this for simplicity
char delimeterStr[2] { ';', '\0' };

for (int uCol = 0; uCol < numCols; uCol++)
{
    if (uCol >= 1)
    {
        const char* test2 = "1704EB18-FE46-4AE4-A90F-06E42C3EE07A"; // Just a test GUID
        memcpy(buff, test2, 37); // Just testing some logic, copy the string into the buffer 

        strcat(pLocalArray[uRow], delimeterStr); // This works just fine if I stop here
        // strcat(pLocalArray[uRow], buff); // ***** If I uncomment out this line, it throws a heap exception

        std::cout << "Check 3 -- Output is: " << pLocalArray[uRow] << endl; // Output: MyFirstString|MySecondString|MyThirdString;1704EB18-FE46-4AE4-A90F-06E42C3EE07A
        std::memset(buff, '\0', sizeof(buff));
        std::cout << "Check 4 -- Output is: " << pLocalArray[uRow] << endl; //Sanity check - MyFirstString|MySecondString|MyThirdString;1704EB18-FE46-4AE4-A90F-06E42C3EE07A
    }
    else
    {
        const char* test = "MyFirstString|MySecondString|MyThirdString";
        memcpy(buff, test, 43);
        pLocalArray[uRow] = _strdup(buff);

        std::cout << "Check -- Output is: " << pLocalArray[uRow] << endl; // Output: MyFirstString|MySecondString|MyThirdString
        std::memset(buff, '\0', sizeof(buff));
        std::cout << "Check 2 -- Output is: " << pLocalArray[uRow] << endl; //Sanity check - Output: MyFirstString|MySecondString|MyThirdString
    }
}
//...

However, as you can see from the comments, Its throwing an exception when I use the second strcat call. I'm not understanding why doing the strcat on the delimiter is working just fine, but appending the delimiter and then immediately appending the GUID string does not work. Can someone point out to me what I'm doing incorrectly or not taking into account?

1 Answers

You may be misunderstanding how the strdup function works. In the following line:

    pLocalArray[uRow] = _strdup(buff);

which is called to initially allocate memory for pLocalArray[uRow], the amount of space allocated will be the actual length of the buff string, interpreted as a nul-terminated character array; this will be the length of the "MyFirstString|MySecondString|MyThirdString" literal, rather than the specified size of the buff array.

Then, when you later try to append a string to that, you are overflowing the allocated space (your first strcat only seems to work, but it is nevertheless undefined behaviour).

To allow space for up to 511 characters (plus the nul-terminator), you will need code like the following:

    pLocalArray[uRow] = malloc(sizeof(buff)); // Allocate full size of "buff"
    strcpy(pLocalArray[uRow], buff); // then copy the strung data
Related