Merge branch 'master' into taintedallocfp

This commit is contained in:
Jonas Jensen
2019-06-19 15:35:09 +02:00
committed by GitHub
224 changed files with 10236 additions and 785 deletions

View File

@@ -0,0 +1,27 @@
| file://:0:0:0:0 | abc | test.cpp:53:6:53:11 | chars1 |
| file://:0:0:0:0 | {...} | test.cpp:38:22:38:22 | v |
| test.cpp:4:9:4:11 | 10 | test.cpp:4:6:4:6 | v |
| test.cpp:5:15:5:16 | & ... | test.cpp:5:7:5:11 | ptr_v |
| test.cpp:6:15:6:15 | v | test.cpp:6:7:6:11 | ref_v |
| test.cpp:8:6:8:7 | 11 | test.cpp:4:6:4:6 | v |
| test.cpp:10:10:10:11 | 13 | test.cpp:6:7:6:11 | ref_v |
| test.cpp:11:6:11:10 | ... + ... | test.cpp:4:6:4:6 | v |
| test.cpp:19:32:19:35 | 0.0 | test.cpp:19:27:19:28 | _y |
| test.cpp:19:42:19:43 | _x | test.cpp:24:8:24:8 | x |
| test.cpp:19:49:19:50 | _y | test.cpp:24:11:24:11 | y |
| test.cpp:19:54:19:60 | 0.0 | test.cpp:24:14:24:14 | z |
| test.cpp:35:16:35:25 | {...} | test.cpp:35:11:35:12 | v1 |
| test.cpp:35:17:35:17 | 1 | test.cpp:31:6:31:8 | num |
| test.cpp:35:20:35:24 | One | test.cpp:32:14:32:16 | str |
| test.cpp:36:16:36:39 | {...} | test.cpp:36:11:36:12 | v2 |
| test.cpp:36:24:36:24 | 2 | test.cpp:31:6:31:8 | num |
| test.cpp:36:34:36:38 | Two | test.cpp:32:14:32:16 | str |
| test.cpp:38:27:38:27 | 3 | test.cpp:31:6:31:8 | num |
| test.cpp:38:30:38:36 | Three | test.cpp:32:14:32:16 | str |
| test.cpp:48:16:48:28 | {...} | test.cpp:48:11:48:12 | v3 |
| test.cpp:48:17:48:27 | {...} | test.cpp:45:12:45:14 | ms2 |
| test.cpp:48:18:48:18 | 4 | test.cpp:31:6:31:8 | num |
| test.cpp:48:21:48:26 | Four | test.cpp:32:14:32:16 | str |
| test.cpp:52:19:52:27 | {...} | test.cpp:52:5:52:11 | myArray |
| test.cpp:54:17:54:31 | {...} | test.cpp:54:6:54:11 | chars2 |
| test.cpp:55:16:55:20 | abc | test.cpp:55:7:55:12 | chars3 |

View File

@@ -0,0 +1,4 @@
import cpp
from Variable v
select v.getAnAssignedValue(), v

View File

@@ -0,0 +1,55 @@
void test1()
{
int v = 10; // assignment to `v`
int *ptr_v = &v; // assignment to `ptr_v`
int &ref_v = v; // assignment to `ref_v`
v = 11; // assignment to `v`
*ptr_v = 12;
ref_v = 13; // assignment to `ref_v`
v = v + 1; // assignment to `v`
v += 1;
v++;
}
class myClass1
{
public:
myClass1(float _x, float _y = 0.0f) : x(_x), y(_y), z(0.0f) { // assignments to `_y`, `x`, `y`, `z`
// ...
}
private:
float x, y, z;
};
// ---
struct myStruct1
{
int num;
const char *str;
};
myStruct1 v1 = {1, "One"}; // assigments to `v1`, `num`, `str`
myStruct1 v2 = {.num = 2, .str = "Two"}; // assigments to `v2`, `num`, `str`
void test2(myStruct1 v = {3, "Three"}) // assignments to `v` (literal `{...}` has no location), `num`, `str`
{
// ...
}
struct myStruct2
{
myStruct1 ms2;
};
myStruct2 v3 = {{4, "Four"}}; // assigments to `v3`, `ms2`, `num`, `str`
// ---
int myArray[10] = {1, 2, 3}; // assigment to `myArray`
char chars1[] = "abc"; // assignment to `chars1` (literal "abc" has no location)
char chars2[] = {'a', 'b', 'c'}; // assigment to `chars2`
char *chars3 = "abc"; // assigment to `chars3`

View File

@@ -0,0 +1,40 @@
class EraInfo
{
public:
EraInfo() {
};
EraInfo(int year, int month, int day) {
};
EraInfo(int Era, int foo, int year, int month, int day, const wchar_t * eraName)
{
}
static EraInfo * EraInfoFromDate(int Era, int foo, int year, int month, int day, wchar_t * eraName)
{
return new EraInfo(Era, foo, year, month, day, eraName);
}
};
int Main()
{
// BAD: constructor creating a EraInfo with exact Heisei era start date
EraInfo * pDateTimeUtil = new EraInfo(1989, 1, 8);
// BAD: constructor creating a EraInfo with exact Heisei era start date
EraInfo * pDateTimeUtil1 = new EraInfo(1, 2, 1989, 1, 8, L"\u5e73\u6210");
// Good: constructor creating a EraInfo with another date
EraInfo * pDateTimeUtil2 = new EraInfo(1, 2, 1900, 1, 1, L"foo");
// BAD: method call passing exact Haisei era start date as parameters
EraInfo * pDateTimeUtil3 = EraInfo::EraInfoFromDate(1, 2, 1989, 1, 8, L"\u5e73\u6210");
// GOOD: method call with the same parameters in a different order (we only track year, month, day)
EraInfo * pDateTimeUtil4 = EraInfo::EraInfoFromDate(1, 2, 8, 1, 1989, L"\u5e73\u6210");
}

View File

@@ -0,0 +1,3 @@
| ConstructorOrMethodWithExactDate.cpp:27:31:27:53 | call to EraInfo | Call that appears to have hard-coded Japanese era start date as parameter. |
| ConstructorOrMethodWithExactDate.cpp:30:32:30:77 | call to EraInfo | Call that appears to have hard-coded Japanese era start date as parameter. |
| ConstructorOrMethodWithExactDate.cpp:36:32:36:55 | call to EraInfoFromDate | Call that appears to have hard-coded Japanese era start date as parameter. |

View File

@@ -0,0 +1 @@
Likely Bugs/JapaneseEra/ConstructorOrMethodWithExactEraDate.ql

View File

@@ -0,0 +1,57 @@
typedef unsigned short WORD;
struct tm
{
int tm_sec; // seconds after the minute - [0, 60] including leap second
int tm_min; // minutes after the hour - [0, 59]
int tm_hour; // hours since midnight - [0, 23]
int tm_mday; // day of the month - [1, 31]
int tm_mon; // months since January - [0, 11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday - [0, 6]
int tm_yday; // days since January 1 - [0, 365]
int tm_isdst; // daylight savings time flag
};
typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
int main()
{
// BAD: Creation of tm stuct corresponding to the beginning of Heisei era
tm *timeTm = new tm();
timeTm->tm_year = 1989;
timeTm->tm_mon = 1;
timeTm->tm_mday = 8;
// GOOD: Creation of tm stuct with different date
tm *timeTm1 = new tm();
timeTm1->tm_year = 1988;
timeTm1->tm_mon = 1;
timeTm1->tm_mday = 1;
// BAD: Creation of SYSTEMTIME stuct corresponding to the beginning of Heisei era
SYSTEMTIME st;
st.wDay = 8;
st.wMonth = 1;
st.wYear = 1989;
// GOOD: Creation of SYSTEMTIME stuct with a different date
SYSTEMTIME st1;
st1.wDay = 1;
st1.wMonth = 1;
st1.wYear = 1990;
return 0;
}

View File

@@ -0,0 +1,2 @@
| StructWithExactDate.cpp:31:13:31:19 | tm_year | A time struct that is initialized with exact Japanese calendar era start date. |
| StructWithExactDate.cpp:46:8:46:12 | wYear | A time struct that is initialized with exact Japanese calendar era start date. |

View File

@@ -0,0 +1 @@
Likely Bugs/JapaneseEra/StructWithExactEraDate.ql

View File

@@ -0,0 +1,11 @@
| test.cpp:314:5:314:9 | wYear | Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found. | test.cpp:12:7:12:11 | wYear | wYear | test.cpp:309:13:309:14 | st | st |
| test.cpp:327:5:327:9 | wYear | Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found. | test.cpp:12:7:12:11 | wYear | wYear | test.cpp:322:13:322:14 | st | st |
| test.cpp:338:6:338:10 | wYear | Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found. | test.cpp:12:7:12:11 | wYear | wYear | test.cpp:333:62:333:63 | st | st |
| test.cpp:484:5:484:9 | wYear | Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found. | test.cpp:12:7:12:11 | wYear | wYear | test.cpp:480:13:480:14 | st | st |
| test.cpp:497:5:497:9 | wYear | Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found. | test.cpp:12:7:12:11 | wYear | wYear | test.cpp:492:13:492:14 | st | st |
| test.cpp:509:5:509:9 | wYear | Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found. | test.cpp:12:7:12:11 | wYear | wYear | test.cpp:505:13:505:14 | st | st |
| test.cpp:606:11:606:17 | tm_year | Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found. | test.cpp:56:6:56:12 | tm_year | tm_year | test.cpp:602:12:602:19 | timeinfo | timeinfo |
| test.cpp:634:11:634:17 | tm_year | Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found. | test.cpp:56:6:56:12 | tm_year | tm_year | test.cpp:628:12:628:19 | timeinfo | timeinfo |
| test.cpp:636:11:636:17 | tm_year | Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found. | test.cpp:56:6:56:12 | tm_year | tm_year | test.cpp:628:12:628:19 | timeinfo | timeinfo |
| test.cpp:640:5:640:9 | wYear | Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found. | test.cpp:12:7:12:11 | wYear | wYear | test.cpp:629:13:629:14 | st | st |
| test.cpp:642:5:642:9 | wYear | Field $@ on variable $@ has been modified, but no appropriate check for LeapYear was found. | test.cpp:12:7:12:11 | wYear | wYear | test.cpp:629:13:629:14 | st | st |

View File

@@ -0,0 +1 @@
Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql

View File

@@ -0,0 +1,3 @@
| test.cpp:317:2:317:21 | call to SystemTimeToFileTime | Return value of $@ function should be verified to check for any error because variable $@ is not guaranteed to be safe. | test.cpp:63:1:63:20 | SystemTimeToFileTime | SystemTimeToFileTime | test.cpp:309:13:309:14 | st | st |
| test.cpp:330:2:330:21 | call to SystemTimeToFileTime | Return value of $@ function should be verified to check for any error because variable $@ is not guaranteed to be safe. | test.cpp:63:1:63:20 | SystemTimeToFileTime | SystemTimeToFileTime | test.cpp:322:13:322:14 | st | st |
| test.cpp:341:2:341:21 | call to SystemTimeToFileTime | Return value of $@ function should be verified to check for any error because variable $@ is not guaranteed to be safe. | test.cpp:63:1:63:20 | SystemTimeToFileTime | SystemTimeToFileTime | test.cpp:333:62:333:63 | st | st |

View File

@@ -0,0 +1 @@
Likely Bugs/Leap Year/UncheckedReturnValueForTimeFunctions.ql

View File

@@ -0,0 +1,658 @@
typedef unsigned short WORD;
typedef unsigned long DWORD, HANDLE;
typedef int BOOL, BOOLEAN, errno_t;
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
typedef unsigned short WCHAR; // wc, 16-bit UNICODE character
typedef long __time64_t, time_t;
#define NULL 0
typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;
typedef struct _TIME_ZONE_INFORMATION {
LONG Bias;
WCHAR StandardName[32];
SYSTEMTIME StandardDate;
LONG StandardBias;
WCHAR DaylightName[32];
SYSTEMTIME DaylightDate;
LONG DaylightBias;
} TIME_ZONE_INFORMATION, *PTIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
typedef struct _TIME_DYNAMIC_ZONE_INFORMATION {
LONG Bias;
WCHAR StandardName[32];
SYSTEMTIME StandardDate;
LONG StandardBias;
WCHAR DaylightName[32];
SYSTEMTIME DaylightDate;
LONG DaylightBias;
WCHAR TimeZoneKeyName[128];
BOOLEAN DynamicDaylightTimeDisabled;
} DYNAMIC_TIME_ZONE_INFORMATION, *PDYNAMIC_TIME_ZONE_INFORMATION;
struct tm
{
int tm_sec; // seconds after the minute - [0, 60] including leap second
int tm_min; // minutes after the hour - [0, 59]
int tm_hour; // hours since midnight - [0, 23]
int tm_mday; // day of the month - [1, 31]
int tm_mon; // months since January - [0, 11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday - [0, 6]
int tm_yday; // days since January 1 - [0, 365]
int tm_isdst; // daylight savings time flag
};
BOOL
SystemTimeToFileTime(
const SYSTEMTIME* lpSystemTime,
LPFILETIME lpFileTime
);
BOOL
FileTimeToSystemTime(
const FILETIME* lpFileTime,
LPSYSTEMTIME lpSystemTime
);
BOOL
SystemTimeToTzSpecificLocalTime(
const TIME_ZONE_INFORMATION* lpTimeZoneInformation,
const SYSTEMTIME* lpUniversalTime,
LPSYSTEMTIME lpLocalTime
);
BOOL
SystemTimeToTzSpecificLocalTimeEx(
const DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation,
const SYSTEMTIME* lpUniversalTime,
LPSYSTEMTIME lpLocalTime
);
BOOL
TzSpecificLocalTimeToSystemTime(
const TIME_ZONE_INFORMATION* lpTimeZoneInformation,
const SYSTEMTIME* lpLocalTime,
LPSYSTEMTIME lpUniversalTime
);
BOOL
TzSpecificLocalTimeToSystemTimeEx(
const DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation,
const SYSTEMTIME* lpLocalTime,
LPSYSTEMTIME lpUniversalTime
);
void GetSystemTime(
LPSYSTEMTIME lpSystemTime
);
void GetSystemTimeAsFileTime(
LPFILETIME lpSystemTimeAsFileTime
);
__time64_t _mkgmtime64(
struct tm* _Tm
);
__time64_t _mkgmtime(
struct tm* const _Tm
)
{
return _mkgmtime64(_Tm);
}
__time64_t mktime(
struct tm* const _Tm
)
{
return _mkgmtime64(_Tm);
}
__time64_t _time64(
__time64_t* _Time
);
__time64_t time(
time_t* const _Time
)
{
return _time64(_Time);
}
int gmtime_s(
struct tm* _Tm,
__time64_t const* _Time
);
BOOL
GetFileTime(
HANDLE hFile,
LPFILETIME lpCreationTime,
LPFILETIME lpLastAccessTime,
LPFILETIME lpLastWriteTime
);
void Correct_FileTimeToSystemTime(const FILETIME* lpFileTime)
{
SYSTEMTIME systemTime;
if (!FileTimeToSystemTime(lpFileTime, &systemTime))
{
/// handle error
return;
}
/// Normal usage
}
void AntiPattern_FileTimeToSystemTime(const FILETIME* lpFileTime)
{
SYSTEMTIME systemTime;
// (out-of-scope) GeneralBug
FileTimeToSystemTime(lpFileTime, &systemTime);
}
void Correct_SystemTimeToTzSpecificLocalTime(const TIME_ZONE_INFORMATION *lpTimeZoneInformation, const SYSTEMTIME *lpUniversalTime)
{
SYSTEMTIME localTime;
if (!SystemTimeToTzSpecificLocalTime(lpTimeZoneInformation, lpUniversalTime, &localTime))
{
/// handle error
return;
}
/// Normal usage
}
void AntiPattern_SystemTimeToTzSpecificLocalTime(const TIME_ZONE_INFORMATION *lpTimeZoneInformation, const SYSTEMTIME *lpUniversalTime)
{
SYSTEMTIME localTime;
// (out-of-scope) GeneralBug
SystemTimeToTzSpecificLocalTime(lpTimeZoneInformation, lpUniversalTime, &localTime);
}
void Correct_SystemTimeToTzSpecificLocalTimeEx(const DYNAMIC_TIME_ZONE_INFORMATION *lpTimeZoneInformation, const SYSTEMTIME *lpUniversalTime)
{
SYSTEMTIME localTime;
if (!SystemTimeToTzSpecificLocalTimeEx(lpTimeZoneInformation, lpUniversalTime, &localTime))
{
/// handle error
return;
}
/// Normal usage
}
void AntiPattern_SystemTimeToTzSpecificLocalTimeEx(const DYNAMIC_TIME_ZONE_INFORMATION *lpTimeZoneInformation, const SYSTEMTIME *lpUniversalTime)
{
SYSTEMTIME localTime;
// (out-of-scope) GeneralBug
SystemTimeToTzSpecificLocalTimeEx(lpTimeZoneInformation, lpUniversalTime, &localTime);
}
void Correct_TzSpecificLocalTimeToSystemTime(const TIME_ZONE_INFORMATION *lpTimeZoneInformation, const SYSTEMTIME *lpLocalTime)
{
SYSTEMTIME universalTime;
if (!TzSpecificLocalTimeToSystemTime(lpTimeZoneInformation, lpLocalTime, &universalTime))
{
/// handle error
return;
}
/// Normal usage
}
void AntiPattern_TzSpecificLocalTimeToSystemTime(const TIME_ZONE_INFORMATION *lpTimeZoneInformation, const SYSTEMTIME *lpLocalTime)
{
SYSTEMTIME universalTime;
// (out-of-scope) GeneralBug
TzSpecificLocalTimeToSystemTime(lpTimeZoneInformation, lpLocalTime, &universalTime);
}
void Correct_TzSpecificLocalTimeToSystemTimeEx(const DYNAMIC_TIME_ZONE_INFORMATION *lpTimeZoneInformation, const SYSTEMTIME *lpLocalTime)
{
SYSTEMTIME universalTime;
if (!TzSpecificLocalTimeToSystemTimeEx(lpTimeZoneInformation, lpLocalTime, &universalTime))
{
/// handle error
return;
}
/// Normal usage
}
void AntiPattern_TzSpecificLocalTimeToSystemTimeEx(const DYNAMIC_TIME_ZONE_INFORMATION *lpTimeZoneInformation, const SYSTEMTIME *lpLocalTime)
{
SYSTEMTIME universalTime;
// (out-of-scope) GeneralBug
TzSpecificLocalTimeToSystemTimeEx(lpTimeZoneInformation, lpLocalTime, &universalTime);
}
/*************************************************
SYSTEMTIME Cases
*************************************************/
void Correct_filetime_conversion_check(SYSTEMTIME& st)
{
FILETIME ft;
if (!SystemTimeToFileTime(&st, &ft))
{
/// Something failed, handle error
return;
}
/// SystemTimeToFileTime succeeded
}
//////////////////////////////////////////////
void AntiPattern_unchecked_filetime_conversion(SYSTEMTIME& st)
{
FILETIME ft;
// (out-of-scope) GeneralBug: Unchecked call to SystemTimeToFileTime. this may have failed, but we didn't check the return value!
SystemTimeToFileTime(&st, &ft);
}
void AntiPattern_unchecked_filetime_conversion2(SYSTEMTIME* st)
{
FILETIME ft;
if (st != NULL)
{
// (out-of-scope) GeneralBug: Unchecked call to SystemTimeToFileTime. this may have failed, but we didn't check the return value!
SystemTimeToFileTime(st, &ft);
}
}
void AntiPattern_unchecked_filetime_conversion2()
{
SYSTEMTIME st;
FILETIME ft;
GetSystemTime(&st);
st.wDay++;
// (out-of-scope) GeneralBug: Not checking is OK, no struct manipulation
SystemTimeToFileTime(&st, &ft);
}
void AntiPattern_unchecked_filetime_conversion2a()
{
SYSTEMTIME st;
FILETIME ft;
GetSystemTime(&st);
// BUG - UncheckedLeapYearAfterYearModification
st.wYear += 2;
// BUG - UncheckedReturnValueForTimeFunctions
SystemTimeToFileTime(&st, &ft);
}
void AntiPattern_unchecked_filetime_conversion2b()
{
SYSTEMTIME st;
FILETIME ft;
GetSystemTime(&st);
// BUG - UncheckedLeapYearAfterYearModification
st.wYear++;
// BUG - UncheckedReturnValueForTimeFunctions
SystemTimeToFileTime(&st, &ft);
}
void AntiPattern_unchecked_filetime_conversion2b(SYSTEMTIME* st)
{
FILETIME ft;
// BUG - UncheckedLeapYearAfterYearModification
st->wYear++;
// BUG - UncheckedReturnValueForTimeFunctions
SystemTimeToFileTime(st, &ft);
}
void AntiPattern_unchecked_filetime_conversion3()
{
SYSTEMTIME st;
FILETIME ft;
GetSystemTime(&st);
if (st.wMonth < 12)
{
st.wMonth++;
}
else
{
// Check for leap year, but...
st.wMonth = 1;
st.wYear++;
}
// (out-of-scope) GeneralBug: Not checking if newly generated date is valid for conversion
SystemTimeToFileTime(&st, &ft);
}
//////////////////////////////////////////////
void CorrectPattern_check1()
{
SYSTEMTIME st;
GetSystemTime(&st);
st.wYear++;
// Guard
if (st.wMonth == 2 && st.wDay == 29)
{
// move back a day when landing on Feb 29 in an non-leap year
bool isLeapYear = st.wYear % 4 == 0 && (st.wYear % 100 != 0 || st.wYear % 400 == 0);
if (!isLeapYear)
{
st.wDay = 28;
}
}
// Safe to use
AntiPattern_unchecked_filetime_conversion(st);
}
void CorrectPattern_check2(int yearsToAdd)
{
SYSTEMTIME st;
GetSystemTime(&st);
st.wYear += yearsToAdd;
// Guard
bool isLeapYear = st.wYear % 4 == 0 && (st.wYear % 100 != 0 || st.wYear % 400 == 0);
st.wDay = st.wMonth == 2 && st.wDay == 29 && !isLeapYear ? 28 : st.wDay;
// Safe to use
AntiPattern_unchecked_filetime_conversion(st);
}
bool isLeapYear(SYSTEMTIME& st)
{
return st.wYear % 4 == 0 && (st.wYear % 100 != 0 || st.wYear % 400 == 0);
}
void CorrectPattern_check3()
{
SYSTEMTIME st;
GetSystemTime(&st);
st.wYear++;
// Guard
if (st.wMonth == 2 && st.wDay == 29 && isLeapYear(st))
{
// move back a day when landing on Feb 29 in an non-leap year
st.wDay = 28;
}
// Safe to use
AntiPattern_unchecked_filetime_conversion(st);
}
bool isLeapYear2(int year)
{
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
bool fixDate(int day, int month, int year)
{
return (month == 2 && day == 29 && isLeapYear2(year));
}
void CorrectPattern_check4()
{
SYSTEMTIME st;
GetSystemTime(&st);
///// FP
st.wYear++;
// Guard
if (fixDate(st.wDay, st.wMonth, st.wYear))
{
// move back a day when landing on Feb 29 in an non-leap year
st.wDay = 28;
}
// Safe to use
AntiPattern_unchecked_filetime_conversion(st);
}
void CorrectPattern_NotManipulated_DateFromAPI_0()
{
SYSTEMTIME st;
GetSystemTime(&st);
FILETIME ft;
// Not checking is OK, no struct manipulation
SystemTimeToFileTime(&st, &ft);
}
void CorrectPattern_NotManipulated_DateFromAPI_1(HANDLE hWatchdog)
{
SYSTEMTIME st;
FILETIME ft;
GetFileTime(hWatchdog, NULL, NULL, &ft);
FileTimeToSystemTime(&ft, &st);
}
/////////////////////////////////////////////////////////////////
void AntiPattern_1_year_addition()
{
SYSTEMTIME st;
GetSystemTime(&st);
// BUG - UncheckedLeapYearAfterYearModification
st.wYear++;
// Usage of potentially invalid date
Correct_filetime_conversion_check(st);
}
void AntiPattern_simple_addition(int yearAddition)
{
SYSTEMTIME st;
GetSystemTime(&st);
// BUG - UncheckedLeapYearAfterYearModification
st.wYear += yearAddition;
// Usage of potentially invalid date
Correct_filetime_conversion_check(st);
}
void AntiPattern_IncorrectGuard(int yearsToAdd)
{
SYSTEMTIME st;
GetSystemTime(&st);
// BUG - UncheckedLeapYearAfterYearModification
st.wYear += yearsToAdd;
// Incorrect Guard
if (st.wMonth == 2 && st.wDay == 29)
{
// Part of a different anti-pattern.
// Make sure the guard includes the proper check
bool isLeapYear = st.wYear % 4 == 0;
if (!isLeapYear)
{
st.wDay = 28;
}
}
// Potentially Unsafe to use
Correct_filetime_conversion_check(st);
}
/*************************************************
struct tm Cases
*************************************************/
void CorrectUsageOf_mkgmtime(struct tm& timeinfo)
{
if (_mkgmtime(&timeinfo) == -1)
{
/// Something failed, handle error
return;
}
/// _mkgmtime succeeded
}
void AntiPattern_uncheckedUsageOf_mkgmtime(struct tm& timeinfo)
{
// (out-of-scope) GeneralBug: Must check return value for _mkgmtime
// QLNOTE: Include other related _mkgmtime* functions in the function name pattern
_mkgmtime(&timeinfo);
// _mktime64(&timeinfo);
// _mktime32(&timeinfo);
}
//////////////////////////////////////////////////////////
void Correct_year_addition_struct_tm()
{
time_t rawtime;
struct tm timeinfo;
time(&rawtime);
// NOTE: Should ideally check return value for this function (not in scope)
errno_t err = gmtime_s(&timeinfo, &rawtime);
if (err)
{
/// handle error
return;
}
// this is the potentially dangerous part, when not followed up with leap year checks
timeinfo.tm_year++;
// Guard
// move back a day when landing on Feb 29 in an non-leap year
bool isLeapYear = timeinfo.tm_year % 4 == 0 && (timeinfo.tm_year % 100 != 0 || (timeinfo.tm_year + 1900) % 400 == 0);
timeinfo.tm_mday = timeinfo.tm_mon == 1 && timeinfo.tm_mday == 29 && !isLeapYear ? 28 : timeinfo.tm_mday;
// safe to use
AntiPattern_uncheckedUsageOf_mkgmtime(timeinfo);
}
void Correct_LinuxPattern()
{
time_t rawtime;
struct tm timeinfo;
time(&rawtime);
// NOTE: Should ideally check return value for this function (not in scope)
errno_t err = gmtime_s(&timeinfo, &rawtime);
/* from 1900 -> from 1980 */
timeinfo.tm_year -= 80;
/* 0~11 -> 1~12 */
timeinfo.tm_mon++;
/* 0~59 -> 0~29(2sec counts) */
timeinfo.tm_sec >>= 1;
// safe to use
AntiPattern_uncheckedUsageOf_mkgmtime(timeinfo);
}
//////////////////////////////////////////
void AntiPattern_year_addition_struct_tm()
{
time_t rawtime;
struct tm timeinfo;
time(&rawtime);
gmtime_s(&timeinfo, &rawtime);
// BUG - UncheckedLeapYearAfterYearModification
timeinfo.tm_year++;
// Usage of potentially invalid date
CorrectUsageOf_mkgmtime(timeinfo);
}
/////////////////////////////////////////////////////////
void FalsePositiveTests(int x)
{
struct tm timeinfo;
SYSTEMTIME st;
timeinfo.tm_year = x;
timeinfo.tm_year = 1970;
st.wYear = x;
st.wYear = 1900 + x;
}
void FalseNegativeTests(int x)
{
struct tm timeinfo;
SYSTEMTIME st;
timeinfo.tm_year = x;
// BUG - UncheckedLeapYearAfterYearModification
timeinfo.tm_year = x + timeinfo.tm_year;
// BUG - UncheckedLeapYearAfterYearModification
timeinfo.tm_year = 1970 + timeinfo.tm_year;
st.wYear = x;
// BUG - UncheckedLeapYearAfterYearModification
st.wYear = x + st.wYear;
// BUG - UncheckedLeapYearAfterYearModification
st.wYear = (1986 + st.wYear) - 1;
}
// False positive
inline void
IncrementMonth(LPSYSTEMTIME pst)
{
if (pst->wMonth < 12)
{
pst->wMonth++;
}
else
{
pst->wMonth = 1;
pst->wYear++;
}
}

View File

@@ -0,0 +1,2 @@
| test.cpp:173:29:173:38 | qwLongTime | This arithmetic operation $@ uses a constant value of 365 ends up modifying the date/time located at $@, without considering leap year scenarios. | test.cpp:170:2:170:47 | ... += ... | ... += ... | test.cpp:173:29:173:38 | qwLongTime | qwLongTime |
| test.cpp:174:30:174:39 | qwLongTime | This arithmetic operation $@ uses a constant value of 365 ends up modifying the date/time located at $@, without considering leap year scenarios. | test.cpp:170:2:170:47 | ... += ... | ... += ... | test.cpp:174:30:174:39 | qwLongTime | qwLongTime |

View File

@@ -0,0 +1 @@
Likely Bugs/Leap Year/Adding365daysPerYear.ql

View File

@@ -0,0 +1,178 @@
typedef unsigned short WORD;
typedef unsigned long DWORD, HANDLE;
typedef int BOOL, BOOLEAN, errno_t;
typedef char CHAR;
typedef short SHORT;
typedef long LONG;
typedef unsigned short WCHAR; // wc, 16-bit UNICODE character
typedef long __time64_t, time_t;
#define NULL 0
typedef long long LONGLONG;
typedef unsigned long long ULONGLONG;
typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;
typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME, *LPFILETIME;
typedef struct _TIME_ZONE_INFORMATION {
LONG Bias;
WCHAR StandardName[32];
SYSTEMTIME StandardDate;
LONG StandardBias;
WCHAR DaylightName[32];
SYSTEMTIME DaylightDate;
LONG DaylightBias;
} TIME_ZONE_INFORMATION, *PTIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION;
typedef struct _TIME_DYNAMIC_ZONE_INFORMATION {
LONG Bias;
WCHAR StandardName[32];
SYSTEMTIME StandardDate;
LONG StandardBias;
WCHAR DaylightName[32];
SYSTEMTIME DaylightDate;
LONG DaylightBias;
WCHAR TimeZoneKeyName[128];
BOOLEAN DynamicDaylightTimeDisabled;
} DYNAMIC_TIME_ZONE_INFORMATION, *PDYNAMIC_TIME_ZONE_INFORMATION;
struct tm
{
int tm_sec; // seconds after the minute - [0, 60] including leap second
int tm_min; // minutes after the hour - [0, 59]
int tm_hour; // hours since midnight - [0, 23]
int tm_mday; // day of the month - [1, 31]
int tm_mon; // months since January - [0, 11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday - [0, 6]
int tm_yday; // days since January 1 - [0, 365]
int tm_isdst; // daylight savings time flag
};
BOOL
SystemTimeToFileTime(
const SYSTEMTIME* lpSystemTime,
LPFILETIME lpFileTime
);
BOOL
FileTimeToSystemTime(
const FILETIME* lpFileTime,
LPSYSTEMTIME lpSystemTime
);
BOOL
SystemTimeToTzSpecificLocalTime(
const TIME_ZONE_INFORMATION* lpTimeZoneInformation,
const SYSTEMTIME* lpUniversalTime,
LPSYSTEMTIME lpLocalTime
);
BOOL
SystemTimeToTzSpecificLocalTimeEx(
const DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation,
const SYSTEMTIME* lpUniversalTime,
LPSYSTEMTIME lpLocalTime
);
BOOL
TzSpecificLocalTimeToSystemTime(
const TIME_ZONE_INFORMATION* lpTimeZoneInformation,
const SYSTEMTIME* lpLocalTime,
LPSYSTEMTIME lpUniversalTime
);
BOOL
TzSpecificLocalTimeToSystemTimeEx(
const DYNAMIC_TIME_ZONE_INFORMATION* lpTimeZoneInformation,
const SYSTEMTIME* lpLocalTime,
LPSYSTEMTIME lpUniversalTime
);
void GetSystemTime(
LPSYSTEMTIME lpSystemTime
);
void GetSystemTimeAsFileTime(
LPFILETIME lpSystemTimeAsFileTime
);
__time64_t _mkgmtime64(
struct tm* _Tm
);
__time64_t _mkgmtime(
struct tm* const _Tm
)
{
return _mkgmtime64(_Tm);
}
__time64_t mktime(
struct tm* const _Tm
)
{
return _mkgmtime64(_Tm);
}
__time64_t _time64(
__time64_t* _Time
);
__time64_t time(
time_t* const _Time
)
{
return _time64(_Time);
}
int gmtime_s(
struct tm* _Tm,
__time64_t const* _Time
);
BOOL
GetFileTime(
HANDLE hFile,
LPFILETIME lpCreationTime,
LPFILETIME lpLastAccessTime,
LPFILETIME lpLastWriteTime
);
void antipattern2()
{
// get the current time as a FILETIME
SYSTEMTIME st; FILETIME ft;
GetSystemTime(&st);
SystemTimeToFileTime(&st, &ft);
// convert to a quadword (64-bit integer) to do arithmetic
ULONGLONG qwLongTime;
qwLongTime = (((ULONGLONG)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
// add a year by calculating the ticks in 365 days
// (which may be incorrect when crossing a leap day)
qwLongTime += 365 * 24 * 60 * 60 * 10000000LLU;
// copy back to a FILETIME
ft.dwLowDateTime = (DWORD)(qwLongTime & 0xFFFFFFFF);
ft.dwHighDateTime = (DWORD)(qwLongTime >> 32);
// convert back to SYSTEMTIME for display or other usage
FileTimeToSystemTime(&ft, &st);
}

View File

@@ -0,0 +1,3 @@
| test.cpp:17:6:17:10 | items | There is an array or std::vector allocation with a hard-coded set of 365 elements, which may indicate the number of days in a year without considering leap year scenarios. |
| test.cpp:25:15:25:26 | new[] | There is an array or std::vector allocation with a hard-coded set of 365 elements, which may indicate the number of days in a year without considering leap year scenarios. |
| test.cpp:52:20:52:23 | call to vector | There is an array or std::vector allocation with a hard-coded set of 365 elements, which may indicate the number of days in a year without considering leap year scenarios. |

View File

@@ -0,0 +1 @@
Likely Bugs/Leap Year/UnsafeArrayForDaysOfYear.ql

View File

@@ -0,0 +1,70 @@
template <class T>
class vector {
private:
T _x;
public:
vector(int size)
{
}
T& operator[](int idx) { return _x; }
const T& operator[](int idx) const { return _x; }
};
void ArrayOfDays_Bug(int dayOfYear, int x)
{
// BUG
int items[365];
items[dayOfYear - 1] = x;
}
void ArrayOfDays_Bug2(int dayOfYear, int x)
{
// BUG
int *items = new int[365];
items[dayOfYear - 1] = x;
delete items;
}
void ArrayOfDays_Correct(unsigned long year, int dayOfYear, int x)
{
bool isLeapYear = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
int *items = new int[isLeapYear ? 366 : 365];
items[dayOfYear - 1] = x;
delete[] items;
}
void ArrayOfDays_FalsePositive(int dayOfYear, int x)
{
int items[366];
items[dayOfYear - 1] = x;
}
void VectorOfDays_Bug(int dayOfYear, int x)
{
// BUG
vector<int> items(365);
items[dayOfYear - 1] = x;
}
void VectorOfDays_Correct(unsigned long year, int dayOfYear, int x)
{
bool isLeapYear = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
vector<int> items(isLeapYear ? 366 : 365);
items[dayOfYear - 1] = x;
}
void VectorOfDays_FalsePositive(int dayOfYear, int x)
{
vector<int> items(366);
items[dayOfYear - 1] = x;
}

View File

@@ -0,0 +1,24 @@
| test.cpp:35:2:37:2 | for(...;...;...) ... | test.cpp:35:18:35:23 | ... < ... | 1 | i | { ... } | i | ExprStmt |
| test.cpp:43:2:45:2 | for(...;...;...) ... | test.cpp:43:18:43:26 | ... < ... | | i | { ... } | i | ExprStmt |
| test.cpp:74:2:77:2 | while (...) ... | test.cpp:74:9:74:17 | ... > ... | 1 | count | { ... } | count | ExprStmt |
| test.cpp:84:2:88:2 | while (...) ... | test.cpp:84:9:84:17 | ... > ... | | count | { ... } | count | if (...) ... |
| test.cpp:171:3:173:3 | while (...) ... | test.cpp:171:10:171:43 | ... != ... | 0 | | { ... } | 0 | return ... |
| test.cpp:251:2:255:2 | while (...) ... | test.cpp:251:9:251:12 | loop | 1 | loop | { ... } | loop | return ... |
| test.cpp:263:2:267:2 | while (...) ... | test.cpp:263:9:263:20 | ... && ... | 1 | 1 | { ... } | ... && ... | return ... |
| test.cpp:275:2:279:2 | while (...) ... | test.cpp:275:9:275:13 | ! ... | 1 | stop | { ... } | stop | return ... |
| test.cpp:287:2:291:2 | while (...) ... | test.cpp:287:9:287:20 | ... && ... | 1 | loop | { ... } | loop | return ... |
| test.cpp:299:2:303:2 | while (...) ... | test.cpp:299:9:299:20 | ... && ... | 1 | loop | { ... } | ... && ..., loop | return ... |
| test.cpp:311:2:315:2 | while (...) ... | test.cpp:311:9:311:21 | ... \|\| ... | 1 | ... \|\| ... | { ... } | 0 | return ... |
| test.cpp:323:2:328:2 | while (...) ... | test.cpp:323:9:323:17 | ... ? ... : ... | | b, c | { ... } | c | return ... |
| test.cpp:336:2:341:2 | while (...) ... | test.cpp:336:9:336:21 | ... \|\| ... | 1 | b, c | { ... } | c | return ... |
| test.cpp:348:2:351:17 | do (...) ... | test.cpp:351:11:351:15 | 0 | | { ... } | { ... } | { ... } | return ... |
| test.cpp:361:2:364:2 | while (...) ... | test.cpp:361:9:361:21 | ... \|\| ... | 1 | ... \|\| ... | { ... } | 0 | while (...) ... |
| test.cpp:365:2:368:2 | while (...) ... | test.cpp:365:9:365:13 | ! ... | 1 | stop | { ... } | stop | while (...) ... |
| test.cpp:369:2:373:2 | while (...) ... | test.cpp:369:9:369:21 | ... \|\| ... | 1 | b, c | { ... } | c | do (...) ... |
| test.cpp:374:2:376:17 | do (...) ... | test.cpp:376:11:376:15 | 0 | | do (...) ... | { ... } | { ... } | return ... |
| test.cpp:384:2:386:2 | while (...) ... | test.cpp:384:9:384:12 | 1 | 1 | 1 | { ... } | | return ... |
| test.cpp:394:2:396:2 | while (...) ... | test.cpp:394:9:394:21 | ... , ... | | { ... } | { ... } | | |
| test.cpp:404:3:408:3 | while (...) ... | test.cpp:404:10:404:13 | loop | 1 | loop | { ... } | | |
| test.cpp:416:2:418:2 | for(...;...;...) ... | test.cpp:416:18:416:23 | ... < ... | 1 | i | { ... } | i | return ... |
| test.cpp:424:2:425:2 | for(...;...;...) ... | test.cpp:424:18:424:23 | ... < ... | 1 | i | { ... } | i | return ... |
| test.cpp:433:2:434:2 | for(...;...;...) ... | test.cpp:433:18:433:22 | 0 | 0 | | { ... } | 0 | return ... |

View File

@@ -0,0 +1,13 @@
import cpp
import LoopConditionsConst
from Loop l, Expr condition
where
l.getCondition() = condition
select
l, condition,
concat(int val | loopEntryConst(condition, val) | val.toString(), ", "),
concat(BasicBlock bb | bb.getASuccessor() = l.getStmt() | bb.toString(), ", "),
concat(l.getStmt().toString(), ", "),
concat(BasicBlock bb | bb.getASuccessor() = l.getFollowingStmt() | bb.toString(), ", "),
concat(l.getFollowingStmt().toString(), ", ")

View File

@@ -0,0 +1,10 @@
import cpp
import semmle.code.cpp.controlflow.internal.ConstantExprs
predicate loopEntryConst(Expr condition, int val)
{
exists(LoopEntryConditionEvaluator x, ControlFlowNode loop |
x.isLoopEntry(condition, loop) and
val = x.getValue(condition)
)
}

View File

@@ -8,3 +8,9 @@
| test.cpp:132:9:132:9 | j | The variable $@ may not be initialized here. | test.cpp:126:6:126:6 | j | j |
| test.cpp:219:3:219:3 | x | The variable $@ may not be initialized here. | test.cpp:218:7:218:7 | x | x |
| test.cpp:243:13:243:13 | i | The variable $@ may not be initialized here. | test.cpp:241:6:241:6 | i | i |
| test.cpp:329:9:329:11 | val | The variable $@ may not be initialized here. | test.cpp:321:6:321:8 | val | val |
| test.cpp:336:10:336:10 | a | The variable $@ may not be initialized here. | test.cpp:333:7:333:7 | a | a |
| test.cpp:369:10:369:10 | a | The variable $@ may not be initialized here. | test.cpp:358:7:358:7 | a | a |
| test.cpp:378:9:378:11 | val | The variable $@ may not be initialized here. | test.cpp:359:6:359:8 | val | val |
| test.cpp:417:10:417:10 | j | The variable $@ may not be initialized here. | test.cpp:414:9:414:9 | j | j |
| test.cpp:436:9:436:9 | j | The variable $@ may not be initialized here. | test.cpp:431:9:431:9 | j | j |

View File

@@ -242,4 +242,196 @@ void test21()
v3 = v1 >> i; // BAD: i is not initialized
v3 = v2 >> 1; // BAD: v2 is not initialized [NOT DETECTED]
}
}
int test22() {
bool loop = true;
int val;
while (loop)
{
val = 1;
loop = false;
}
return val; // GOOD
}
int test23() {
bool loop = true, stop = false;
int val;
while (loop && true)
{
val = 1;
loop = false;
}
return val; // GOOD
}
int test24() {
bool stop = false;
int val;
while (!stop)
{
val = 1;
stop = true;
}
return val; // GOOD
}
int test25() {
bool loop = true, stop = false;
int val;
while (true && loop)
{
val = 1;
loop = false;
}
return val; // GOOD
}
int test26() {
bool loop = true, stop = false;
int val;
while (loop && loop)
{
val = 1;
loop = false;
}
return val; // GOOD
}
int test27() {
bool loop = true, stop = false;
int val;
while (loop || false)
{
val = 1;
loop = false;
}
return val; // GOOD
}
int test28() {
bool a = true, b = true, c = true;
int val;
while (a ? b : c)
{
val = 1;
a = false;
c = false;
}
return val; // GOOD [FALSE POSITIVE]
}
int test29() {
bool a, b = true, c = true;
int val;
while ((a && b) || c) // BAD (a is uninitialized)
{
val = 1;
b = false;
c = false;
}
return val; // GOOD
}
int test30() {
int val;
do
{
val = 1;
} while (false);
return val; // GOOD
}
int test31() {
bool loop = true;
bool stop = false;
bool a, b = true, c = true;
int val;
while (loop || false)
{
loop = false;
}
while (!stop)
{
stop = true;
}
while ((a && b) || c) // BAD (a is uninitialized)
{
b = false;
c = false;
}
do
{
} while (false);
return val; // BAD
}
int test32() {
int val;
while (true)
{
}
return val; // GOOD (never reached)
}
int test33() {
int val;
while (val = 1, true) {
return val; // GOOD
}
}
int test34() {
bool loop = true;
int val;
{
while (loop)
{
val = 1;
loop = false;
}
}
return val; // GOOD
}
int test35() {
int i, j;
for (int i = 0; i < 10; i++, j = 1) {
return j; // BAD
}
}
int test36() {
int i, j;
for (int i = 0; i < 10; i++, j = 1) {
}
return j; // GOOD
}
int test38() {
int i, j;
for (int i = 0; false; i++, j = 1) {
}
return j; // BAD
}