Merge pull request #233 from orbitcowboy/master

Fixed #389: Providing negative value to memory allocation function.
This commit is contained in:
Daniel Marjamäki 2014-02-02 10:47:37 -08:00
commit ec61143623
3 changed files with 60 additions and 2 deletions

View File

@ -214,6 +214,15 @@ void CheckBufferOverrun::argumentSizeError(const Token *tok, const std::string &
reportError(tok, Severity::warning, "argumentSize", "The array '" + varname + "' is too small, the function '" + functionName + "' expects a bigger one."); reportError(tok, Severity::warning, "argumentSize", "The array '" + varname + "' is too small, the function '" + functionName + "' expects a bigger one.");
} }
void CheckBufferOverrun::negativeMemoryAllocationSizeError(const Token *tok)
{
reportError(tok, Severity::error, "negativeMemoryAllocationSize",
"Memory allocation size have to be greater or equal to 0.\n"
"Memory allocation size have to be greater or equal to 0."
"The allocation size of memory have to be greater or equal to 0 because"
"negative size have no speficied behaviour.");
}
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -1503,6 +1512,9 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
type = tok->strAt(4); type = tok->strAt(4);
var = tok->next()->variable(); var = tok->next()->variable();
nextTok = 8; nextTok = 8;
if (size < 0) {
negativeMemoryAllocationSizeError(tok->next()->next());
}
} else if (Token::Match(tok, "[*;{}] %var% = new %type% ( %num% )")) { } else if (Token::Match(tok, "[*;{}] %var% = new %type% ( %num% )")) {
size = 1; size = 1;
type = tok->strAt(4); type = tok->strAt(4);
@ -1521,6 +1533,10 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
var = tok->next()->variable(); var = tok->next()->variable();
nextTok = 7; nextTok = 7;
if (size < 0) {
negativeMemoryAllocationSizeError(tok->next()->next());
}
/** @todo false negatives: this may be too conservative */ /** @todo false negatives: this may be too conservative */
if (!var || var->typeEndToken()->str() != "*" || var->typeStartToken()->next() != var->typeEndToken()) if (!var || var->typeEndToken()->str() != "*" || var->typeStartToken()->next() != var->typeEndToken())
continue; continue;
@ -1531,9 +1547,13 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
// malloc() gets count of bytes and not count of // malloc() gets count of bytes and not count of
// elements, so we should calculate count of elements // elements, so we should calculate count of elements
// manually // manually
unsigned int sizeOfType = _tokenizer->sizeOfType(var->typeStartToken()); const unsigned int sizeOfType = _tokenizer->sizeOfType(var->typeStartToken());
if (sizeOfType > 0) if (sizeOfType > 0) {
size /= static_cast<int>(sizeOfType); size /= static_cast<int>(sizeOfType);
}
if (size < 0) {
negativeMemoryAllocationSizeError(tok->next()->next());
}
} else { } else {
continue; continue;
} }

View File

@ -218,6 +218,7 @@ private:
void bufferOverrunError(const Token *tok, const std::string &varnames = ""); void bufferOverrunError(const Token *tok, const std::string &varnames = "");
void bufferOverrunError(const std::list<const Token *> &callstack, const std::string &varnames = ""); void bufferOverrunError(const std::list<const Token *> &callstack, const std::string &varnames = "");
void strncatUsageError(const Token *tok); void strncatUsageError(const Token *tok);
void negativeMemoryAllocationSizeError(const Token *tok); // provide a negative value to memory allocation function
void outOfBoundsError(const Token *tok, const std::string &what, const bool show_size_info, const MathLib::bigint &supplied_size, const MathLib::bigint &actual_size); void outOfBoundsError(const Token *tok, const std::string &what, const bool show_size_info, const MathLib::bigint &supplied_size, const MathLib::bigint &actual_size);
void sizeArgumentAsCharError(const Token *tok); void sizeArgumentAsCharError(const Token *tok);
void terminateStrncpyError(const Token *tok, const std::string &varname); void terminateStrncpyError(const Token *tok, const std::string &varname);
@ -251,6 +252,7 @@ public:
c.possibleReadlinkBufferOverrunError(0, "readlink", "buffer"); c.possibleReadlinkBufferOverrunError(0, "readlink", "buffer");
c.argumentSizeError(0, "function", "array"); c.argumentSizeError(0, "function", "array");
c.writeOutsideBufferSizeError(0,2,3,"write"); c.writeOutsideBufferSizeError(0,2,3,"write");
c.negativeMemoryAllocationSizeError(0);
} }
private: private:

View File

@ -267,6 +267,8 @@ private:
TEST_CASE(readlinkat); TEST_CASE(readlinkat);
TEST_CASE(writeOutsideBufferSize) TEST_CASE(writeOutsideBufferSize)
TEST_CASE(negativeMemoryAllocationSizeError) // #389
} }
@ -4111,6 +4113,40 @@ private:
"}"); "}");
TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Writing 1 bytes outside buffer size.\n", "", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Writing 1 bytes outside buffer size.\n", "", errout.str());
} }
void negativeMemoryAllocationSizeError() { // #389
check("void f()\n"
"{\n"
" int *a;\n"
" a = new int[-1];\n"
" delete [] a;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory allocation size have to be greater or equal to 0.\n", errout.str());
check("void f()\n"
"{\n"
" int *a;\n"
" a = malloc( -10 );\n"
" free(a);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory allocation size have to be greater or equal to 0.\n", errout.str());
check("void f()\n"
"{\n"
" int *a;\n"
" a = malloc( -10);\n"
" free(a);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory allocation size have to be greater or equal to 0.\n", errout.str());
check("void f()\n"
"{\n"
" int *a;\n"
" a = alloca( -10 );\n"
" free(a);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory allocation size have to be greater or equal to 0.\n", errout.str());
}
}; };
REGISTER_TEST(TestBufferOverrun) REGISTER_TEST(TestBufferOverrun)