>
>
>
V505. The 'alloca' function is used ins…


V505. The 'alloca' function is used inside the loop. This can quickly overflow stack.

The analyzer detected that the 'alloca' function is used inside the loop.

The 'alloca' function allocates memory for a specified buffer inside the frame of the caller function. This memory area is cleared only together with the elimination of this frame at the time of the area's termination.

Here is an example:

void foo ()
{
  char *buffer = nullptr;
  buffer = (char *) alloca(256); // <= (1)

  // using buffer
  ....
} // <= (2)

The example is synthetic, but it clearly demonstrates how the 'alloca' function works. On the line labeled (1), a 256-byte memory block is allocated on the stack frame of the 'foo' function, the stack frame is created when the function is called. The stack frame is destroyed on the line (2) when it returns the control flow to the caller. This releases all the memory allocated for it on the stack and help avoid memory leaks.

However, careless use of this function can lead to a problem. The stack memory of the executable program is restricted, and its overflow must be monitored.

Let's take a look at the example:

void bar(int n)
{
  for (size_t i = 0; i < n; ++i)
  {
    char *buffer = nullptr;
    if (buffer = (char*) alloca(256)) // <=
    { 
      // using buffer
      ....
    }
  }
}

The 'alloca' function is called in a loop. The problem is that the allocated memory is not released between the loop's iterations. At the same time, if the number of 'n' iterations is large enough, the run-time stack may overflow.

In this case, it's quite easy to fix the incorrect code. You can do this by calling the 'alloca' function outside the loop and using 'buffer' repeatedly at every iteration:

void bar(int n)
{
  char *buffer = (char*)alloca(256);

  for (size_t i = 0; i < n; ++i)
  {
    // using buffer
    ....
  }
}

Here is another example of dangerous code:

// A2W defined in ATL using alloca
#define A2W(lpa) .... 

void AtlExample()
{
  ....

  size_t n = ....;
  wchar_t** strings = { '\0' };
  LPCSTR* pszSrc = { '\0' };

  for (size_t i = 0; i < n; ++i)
  {
    if (wcscmp(strings[i], A2W(pszSrc[i])) == 0) // <=
    { 
      ....
    }
  }
}

The 'A2W' macro is defined in the 'ATL' library version 3.0. The 'alloca' function is used in the macro. Whether this code leads to errors or not depends on the length of the processed strings, their number and the size of the available stack. You can fix the dangerous code by using the 'CA2W' class defined in the 'ATL' library version 7.0. Unlike a macro, this class allocates memory on the stack only for small strings – for long ones, memory is allocated via 'malloc'. Moreover, the memory allocated on the stack is released when leaving the scope of the variable declaration. Therefore, the memory is released after the comparison with 'strings[i]'.

The corrected example:

// using ATL 7.0
....
for (size_t i = 0; i < n; ++i)
{
  if (wcscmp(strings[i], CA2W(pszSrc[i])) == 0) // <=
  { 
    ....
  }
}

You can read more about the functions of the ATL library in the documentation.

This diagnostic is classified as:

You can look at examples of errors detected by the V505 diagnostic.