mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
cpp - Using the return value of a strcpy or related string copy function in an if statement
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
if(strcpy(szbuf1, "Manager") == 0) // most likely strcmp was intended instead of strcpy
|
||||
{
|
||||
// ...
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>This rule finds uses of the string copy function calls that return the <code>destination</code> parameter,
|
||||
and that do not have a return value reserved to indicate an error.</p>
|
||||
|
||||
<p>The rule flags occurrences using such string copy functions as the conditional of an <code>if</code> statement, either directly, as part of an equality operator or a logical operator.</p>
|
||||
|
||||
<p>The string copy functions that the rule takes into consideration are:
|
||||
<li>strcpy</li>
|
||||
<li>wcscpy</li>
|
||||
<li>_mbscpy</li>
|
||||
<li>strncpy</li>
|
||||
<li>_strncpy_l</li>
|
||||
<li>wcsncpy</li>
|
||||
<li>_wcsncpy_l</li>
|
||||
<li>_mbsncpy</li>
|
||||
<li>_mbsncpy_l</li>
|
||||
</p>
|
||||
|
||||
<p>NOTE: It is highly recommended to consider using a more secure version of string manipulation functions suchas as <code>strcpy_s</code>.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>Check to ensure that the flagged expressions are not typos.</p>
|
||||
<p>If a string comparison is intended, change the function to the appropriate string comparison function.</p>
|
||||
<p>If a string copy is really intended, very likely a secure version of the string copy function such as <code>strcpy_s</code> was intended instead of the insecure version of the string copy function.</p>
|
||||
|
||||
</recommendation>
|
||||
<example><sample src="UsingStrcpyInConditional.cpp" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Microsoft Books on Line: <a href="https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/ccf4h9w8(v=vs.110)">C6324</a></li>
|
||||
<li>Microsoft Books on Line: <a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strcpy-wcscpy-mbscpy?view=vs-2017">strcpy, wcscpy, _mbscpy</a></li>
|
||||
<li>US-CERT: <a href="https://www.us-cert.gov/bsi/articles/knowledge/coding-practices/strcpy_s-and-strcat_s">strncpy_s() and strncat_s()</a></li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @name Using the return value of a strcpy or related string copy function in an if statement
|
||||
* @description The return value for strcpy or related string copy functions have no reserved return value to indicate an error.
|
||||
* Using these functions as part of an if statement condition indicates a logic error.
|
||||
* Either the intent was to use a more secure version of a string copy function (such as strcpy_s),
|
||||
* or a string compare function (such as strcmp).
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id cpp/string-copy-function-in-if-condition
|
||||
* @tags external/microsoft/C6324
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate isStringComparisonFunction(string functionName) {
|
||||
functionName = "strcpy"
|
||||
or functionName = "wcscpy"
|
||||
or functionName = "_mbscpy"
|
||||
or functionName = "strncpy"
|
||||
or functionName = "_strncpy_l"
|
||||
or functionName = "wcsncpy"
|
||||
or functionName = "_wcsncpy_l"
|
||||
or functionName = "_mbsncpy"
|
||||
or functionName = "_mbsncpy_l"
|
||||
}
|
||||
|
||||
from IfStmt ifs,
|
||||
FunctionCall func
|
||||
where isStringComparisonFunction( func.getTarget().getQualifiedName() )
|
||||
and ( func = ifs.getCondition()
|
||||
or exists( UnaryLogicalOperation ule |
|
||||
ule = ifs.getCondition()
|
||||
and func = ule.getAChild()
|
||||
)
|
||||
or exists( BinaryLogicalOperation ble |
|
||||
ble = ifs.getCondition()
|
||||
and func = ble.getAChild()
|
||||
)
|
||||
or exists( EqualityOperation eop |
|
||||
eop = ifs.getCondition()
|
||||
and func = eop.getAChild()
|
||||
)
|
||||
)
|
||||
select func, "Incorrect use of function " + func.getTarget().getQualifiedName() + ". Verify the logic and replace with a secure string copy function, or a string comparison function."
|
||||
@@ -0,0 +1,18 @@
|
||||
| test.c:33:9:33:14 | call to strcpy | Incorrect use of function strcpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.c:37:10:37:15 | call to strcpy | Incorrect use of function strcpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.c:41:9:41:14 | call to strcpy | Incorrect use of function strcpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.c:45:27:45:32 | call to strcpy | Incorrect use of function strcpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.c:49:9:49:15 | call to strncpy | Incorrect use of function strncpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:75:9:75:14 | call to strcpy | Incorrect use of function strcpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:79:10:79:15 | call to strcpy | Incorrect use of function strcpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:83:9:83:14 | call to strcpy | Incorrect use of function strcpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:87:27:87:32 | call to strcpy | Incorrect use of function strcpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:91:9:91:37 | call to wcscpy | Incorrect use of function wcscpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:95:9:95:14 | call to wcscpy | Incorrect use of function wcscpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:99:9:99:15 | call to _mbscpy | Incorrect use of function _mbscpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:103:9:103:15 | call to strncpy | Incorrect use of function strncpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:107:9:107:15 | call to wcsncpy | Incorrect use of function wcsncpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:111:9:111:16 | call to _mbsncpy | Incorrect use of function _mbsncpy. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:115:9:115:18 | call to _strncpy_l | Incorrect use of function _strncpy_l. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:119:9:119:18 | call to _wcsncpy_l | Incorrect use of function _wcsncpy_l. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
| test.cpp:123:9:123:18 | call to _mbsncpy_l | Incorrect use of function _mbsncpy_l. Verify the logic and replace with a secure string copy function, or a string comparison function. |
|
||||
@@ -0,0 +1 @@
|
||||
Likely Bugs/Likely Typos/UsingStrcpyInConditional.ql
|
||||
@@ -0,0 +1,70 @@
|
||||
typedef unsigned int size_t;
|
||||
typedef int* locale_t;
|
||||
|
||||
char* strcpy(char* destination, const char* source)
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
char* strncpy(char* destination, const char* source, size_t count)
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
|
||||
int SomeFunction()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SomeFunctionThatTakesString(char* destination)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int strcmp(char* destination, const char* source)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void PositiveCases()
|
||||
{
|
||||
char szbuf1[100];
|
||||
char szbuf2[100];
|
||||
|
||||
if (strcpy(szbuf1, "test")) // Bug, direct usage
|
||||
{
|
||||
}
|
||||
|
||||
if (!strcpy(szbuf1, "test")) // Bug, unary binary operator
|
||||
{
|
||||
}
|
||||
|
||||
if (strcpy(szbuf1, "test") == 0) // Bug, equality operator
|
||||
{
|
||||
}
|
||||
|
||||
if (SomeFunction() && strcpy(szbuf1, "test")) // Bug, binary logical operator
|
||||
{
|
||||
}
|
||||
|
||||
if (strncpy(szbuf1, "test", 100)) // Bug
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void NegativeCases()
|
||||
{
|
||||
char szbuf1[100];
|
||||
|
||||
if (SomeFunction())
|
||||
{
|
||||
}
|
||||
|
||||
if (SomeFunctionThatTakesString(strcpy(szbuf1, "test")))
|
||||
{
|
||||
}
|
||||
|
||||
if (strcmp(szbuf1, "test"))
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
typedef unsigned long size_t;
|
||||
typedef int* locale_t;
|
||||
|
||||
char* strcpy(char* destination, const char* source)
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
wchar_t* wcscpy(wchar_t* destination, const wchar_t* source)
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
unsigned char* _mbscpy(unsigned char* destination, const unsigned char* source)
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
char* strncpy(char* destination, const char* source, size_t count)
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
wchar_t* wcsncpy(wchar_t* destination, const wchar_t* source, size_t count)
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
unsigned char* _mbsncpy(unsigned char* destination, const unsigned char* source, size_t count)
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
char* _strncpy_l(char* destination, const char* source, size_t count, locale_t locale)
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
wchar_t* _wcsncpy_l(wchar_t* destination, const wchar_t* source, size_t count, locale_t locale)
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
unsigned char* _mbsncpy_l(unsigned char* destination, const unsigned char* source, size_t count, locale_t locale)
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
|
||||
int SomeFunction()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int SomeFunctionThatTakesString(char* destination)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int strcmp(char* destination, const char* source)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int strcpy_s(char* destination, size_t dest_size, const char* source)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define WCSCPY_6324(x,y) wcscpy(x,y)
|
||||
|
||||
void PositiveCases()
|
||||
{
|
||||
char szbuf1[100];
|
||||
char szbuf2[100];
|
||||
wchar_t wscbuf1[100];
|
||||
wchar_t wscbuf2[100];
|
||||
unsigned char mbcbuf1[100];
|
||||
unsigned char mbcbuf2[100];
|
||||
|
||||
locale_t x;
|
||||
*x = 0;
|
||||
|
||||
if (strcpy(szbuf1, "test")) // Bug, direct usage
|
||||
{
|
||||
}
|
||||
|
||||
if (!strcpy(szbuf1, "test")) // Bug, unary binary operator
|
||||
{
|
||||
}
|
||||
|
||||
if (strcpy(szbuf1, "test") == 0) // Bug, equality operator
|
||||
{
|
||||
}
|
||||
|
||||
if (SomeFunction() && strcpy(szbuf1, "test")) // Bug, binary logical operator
|
||||
{
|
||||
}
|
||||
|
||||
if (WCSCPY_6324(wscbuf1, wscbuf2)) // Bug, using a macro
|
||||
{
|
||||
}
|
||||
|
||||
if (wcscpy(wscbuf1, wscbuf2)) // Bug
|
||||
{
|
||||
}
|
||||
|
||||
if (_mbscpy(mbcbuf1, mbcbuf2)) // Bug
|
||||
{
|
||||
}
|
||||
|
||||
if (strncpy(szbuf1, "test", 100)) // Bug
|
||||
{
|
||||
}
|
||||
|
||||
if (wcsncpy(wscbuf1, wscbuf2, 100)) // Bug
|
||||
{
|
||||
}
|
||||
|
||||
if (_mbsncpy(mbcbuf1, (const unsigned char*)"test", 100)) // Bug
|
||||
{
|
||||
}
|
||||
|
||||
if (_strncpy_l(szbuf1, "test", 100, x)) // Bug
|
||||
{
|
||||
}
|
||||
|
||||
if (_wcsncpy_l(wscbuf1, wscbuf2, 100, x)) // Bug
|
||||
{
|
||||
}
|
||||
|
||||
if (_mbsncpy_l(mbcbuf1, (const unsigned char*)"test", 100, x)) //Bug
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NegativeCases()
|
||||
{
|
||||
char szbuf1[100];
|
||||
|
||||
if (SomeFunction())
|
||||
{
|
||||
}
|
||||
|
||||
if (SomeFunctionThatTakesString(strcpy(szbuf1, "test")))
|
||||
{
|
||||
}
|
||||
|
||||
if (strcmp(szbuf1, "test"))
|
||||
{
|
||||
}
|
||||
|
||||
if (strcpy_s(szbuf1, 100, "test"))
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user