Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Buffer is overrun?

Tags:

c++

memory

I am trying to turn a vector of char* into an array of char pointer but I get this annoying error and I can't figure out what I'm doing wrong.

char** Parse::toCommand(std::vector<char*> command) {
    char** array = new char* [command.size()];
    for (int i = 0; i < command.size(); i++) {
        array[i] = command[i];
    }

    return array;
}

I get this warning which causes my program to not run.

 Buffer overrun while writing to 'array':  the writable size is 'command.public: unsigned int __thiscall std::vector<char *,class std::allocator<char *> >::size(void)const ()*4' bytes, but '8' bytes might be written.

the char* is actually a c string of course.

The strings in the vector are pieces of a string that was cut up using strtok_s. I got rid of the Null at the end of every string by converting each to a c str using string::copy() to get a non constant c string and using the constructor of std::string to get a regular string. I then popped the back to rid myself of the null.

My end goal is I want to have an array of c strings so that I can pass it to execvp()

for (int i = 0; i < exes.size(); i++) {  //Separate each executable and argument list into vector of char* and push that to 2d vector of char*

        char* arg = exes[i]; //arg = the entire string executable and arguments
        std::vector <char*> argV;

        char* place = NULL;

        ptr3 = strtok_s(arg, " ", &place);

        while (ptr3 != NULL) {

            if (*ptr3 == '"') {//if beginning of remaining char* begins with ", push char*
                std::string temp;
                temp.push_back(*ptr3);
                ptr3 = strtok_s(NULL, "\"", &place);
                temp.append(ptr3);
                temp.pop_back();
                temp.push_back('"');
                char* cstr = new char[temp.size()];
                temp.copy(cstr, temp.size(), 0);
                argV.push_back(cstr);
            }
            else if (*ptr3 == '#') {
                break;
            }
            else {
                std::string temp(ptr3);
                temp.pop_back();
                char* cstr = new char[temp.size()];
                temp.copy(cstr, temp.size(), 0);
                argV.push_back(cstr);
            }
            ptr3 = strtok_s(NULL, " ", &place);
        }

        argV.push_back(NULL);
        args.push_back(argV);
    }

    for (int i = 0; i < args.size(); i++) {
        char** command = this->toCommand(args[i]);
        commands[i] = new COM(command);
    }

argV is a vector<vector<char*>> and

like image 873
dthecsguy Avatar asked Nov 12 '19 07:11

dthecsguy


People also ask

How does a buffer overrun work?

A buffer overflow, or buffer overrun, occurs when more data is put into a fixed-length buffer than the buffer can handle. The extra information, which has to go somewhere, can overflow into adjacent memory space, corrupting or overwriting the data held in that space.

Is buffer overflow still a problem?

Buffer overflows can be exploited by attackers to corrupt software. Despite being well-understood, buffer overflow attacks are still a major security problem that torment cyber-security teams.


1 Answers

To be clear: this warning is not from the compiler but it's from the Microsoft code analyzer.

I made a complete example that reproduces the warning using Visual Studio 2019. There are no more strings, pointers to pointers and other poor design and the warning is still there.

For me the code is correct and it's simply a bug in the Microsoft code analyzer, or the analyzer is over cautious.

#include <iostream>
#include <vector>

int* toCommand(std::vector<int> command)
{
  int* array = new int [command.size()];
  for (size_t i = 0; i < command.size(); i++) {
    array[i] = command[i];
  }

  return array;
}

int main()
{
  std::vector v{1,2,3};
  int* foo = toCommand(v);
  for (int i = 0; i < 3; i++)
    std::cout << foo[i] << "\n";
}

The warning comes from the Microsoft Code analyzer and it's also displayed directly in the IDE:

enter image description here

This is the simplest example that shows the warning:

int* Foo(int size)
{
  int* array = new int [size];
  array[1] = 1;  // with array[0] = 1; the warning goes away
  return array;
}

warning C6386: Buffer overrun while writing to 'array': the writable size is 'size*4' bytes, but '8' bytes might be written.

like image 99
Jabberwocky Avatar answered Sep 19 '22 18:09

Jabberwocky