mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
CPP: Handle %s/%c/%S/%C correctly on non-MS platforms.
This commit is contained in:
@@ -675,7 +675,7 @@ class FormatLiteral extends Literal {
|
||||
* Gets the char type required by the nth conversion specifier.
|
||||
* - in the base case this is the default for the formatting function
|
||||
* (e.g. `char` for `printf`, `wchar_t` for `wprintf`).
|
||||
* - the `%S` format character reverses wideness.
|
||||
* - the `%C` format character reverses wideness on some platforms.
|
||||
* - the size prefixes 'l'/'w' and 'h' override the type character
|
||||
* to wide or single-byte characters respectively.
|
||||
*/
|
||||
@@ -722,7 +722,7 @@ class FormatLiteral extends Literal {
|
||||
* Gets the string type required by the nth conversion specifier.
|
||||
* - in the base case this is the default for the formatting function
|
||||
* (e.g. `char` for `printf`, `wchar_t` for `wprintf`).
|
||||
* - the `%S` format character reverses wideness.
|
||||
* - the `%S` format character reverses wideness on some platforms.
|
||||
* - the size prefixes 'l'/'w' and 'h' override the type character
|
||||
* to wide or single-byte characters respectively.
|
||||
*/
|
||||
|
||||
@@ -22,7 +22,7 @@ private Type stripTopLevelSpecifiersOnly(Type t) {
|
||||
*/
|
||||
Type getAFormatterWideType() {
|
||||
exists(FormattingFunction ff |
|
||||
result = stripTopLevelSpecifiersOnly(ff.getDefaultCharType()) and
|
||||
result = stripTopLevelSpecifiersOnly(ff.getFormatCharType()) and
|
||||
result.getSize() != 1
|
||||
)
|
||||
}
|
||||
@@ -46,6 +46,14 @@ abstract class FormattingFunction extends Function {
|
||||
/** Gets the position at which the format parameter occurs. */
|
||||
abstract int getFormatParameterIndex();
|
||||
|
||||
/**
|
||||
* Holds if this `FormattingFunction` is in a context that supports
|
||||
* Microsoft rules and extensions.
|
||||
*/
|
||||
predicate isMicrosoft() {
|
||||
getFile().compiledAsMicrosoft()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the default meaning of `%s` is a `wchar_t *`, rather than
|
||||
* a `char *` (either way, `%S` will have the opposite meaning).
|
||||
@@ -71,12 +79,13 @@ abstract class FormattingFunction extends Function {
|
||||
* `char` or `wchar_t`.
|
||||
*/
|
||||
Type getDefaultCharType() {
|
||||
result =
|
||||
stripTopLevelSpecifiersOnly(
|
||||
stripTopLevelSpecifiersOnly(
|
||||
getParameter(getFormatParameterIndex()).getType().getUnderlyingType()
|
||||
).(PointerType).getBaseType()
|
||||
)
|
||||
(
|
||||
isMicrosoft() and
|
||||
result = getFormatCharType()
|
||||
) or (
|
||||
not isMicrosoft() and
|
||||
result instanceof PlainCharType
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
| tests.cpp:18:15:18:22 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' |
|
||||
| tests.cpp:19:15:19:22 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' |
|
||||
| tests.cpp:25:17:25:23 | Hello | This argument should be of type 'wchar_t *' but is of type 'char *' |
|
||||
| tests.cpp:26:17:26:24 | Hello | This argument should be of type 'wchar_t *' but is of type 'char16_t *' |
|
||||
| tests.cpp:30:17:30:24 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' |
|
||||
| tests.cpp:31:17:31:24 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' |
|
||||
| tests.cpp:33:36:33:42 | Hello | This argument should be of type 'char16_t *' but is of type 'char *' |
|
||||
| tests.cpp:35:36:35:43 | Hello | This argument should be of type 'char16_t *' but is of type 'wchar_t *' |
|
||||
| tests.cpp:38:36:38:43 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' |
|
||||
| tests.cpp:39:36:39:43 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' |
|
||||
| tests.cpp:26:17:26:24 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' |
|
||||
| tests.cpp:27:17:27:24 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' |
|
||||
| tests.cpp:34:36:34:43 | Hello | This argument should be of type 'char *' but is of type 'char16_t *' |
|
||||
| tests.cpp:35:36:35:43 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *' |
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| tests.cpp:8:5:8:10 | printf | char | char | char16_t, wchar_t | char16_t, wchar_t |
|
||||
| tests.cpp:9:5:9:11 | wprintf | wchar_t | wchar_t | char | wchar_t |
|
||||
| tests.cpp:10:5:10:12 | swprintf | char16_t | char16_t | char | char16_t |
|
||||
| tests.cpp:9:5:9:11 | wprintf | wchar_t | char | char16_t, wchar_t | char16_t, wchar_t |
|
||||
| tests.cpp:10:5:10:12 | swprintf | char16_t | char | char16_t, wchar_t | char16_t, wchar_t |
|
||||
|
||||
@@ -22,19 +22,19 @@ void tests() {
|
||||
printf("%S", u"Hello"); // GOOD
|
||||
printf("%S", L"Hello"); // GOOD
|
||||
|
||||
wprintf(L"%s", "Hello"); // BAD: expecting wchar_t
|
||||
wprintf(L"%s", u"Hello"); // BAD: expecting wchar_t
|
||||
wprintf(L"%s", L"Hello"); // GOOD
|
||||
wprintf(L"%s", "Hello"); // GOOD
|
||||
wprintf(L"%s", u"Hello"); // BAD: expecting char
|
||||
wprintf(L"%s", L"Hello"); // BAD: expecting char
|
||||
|
||||
wprintf(L"%S", "Hello"); // GOOD
|
||||
wprintf(L"%S", u"Hello"); // BAD: expecting char
|
||||
wprintf(L"%S", L"Hello"); // BAD: expecting char
|
||||
wprintf(L"%S", "Hello"); // BAD: expecting wchar_t [NOT DETECTED]
|
||||
wprintf(L"%S", u"Hello"); // BAD: expecting wchar_t [NOT DETECTED]
|
||||
wprintf(L"%S", L"Hello"); // GOOD
|
||||
|
||||
swprintf(buffer, BUF_SIZE, u"%s", "Hello"); // BAD: expecting char16_t
|
||||
swprintf(buffer, BUF_SIZE, u"%s", u"Hello"); // GOOD
|
||||
swprintf(buffer, BUF_SIZE, u"%s", L"Hello"); // BAD: expecting char16_t
|
||||
swprintf(buffer, BUF_SIZE, u"%s", "Hello"); // GOOD
|
||||
swprintf(buffer, BUF_SIZE, u"%s", u"Hello"); // BAD: expecting char
|
||||
swprintf(buffer, BUF_SIZE, u"%s", L"Hello"); // BAD: expecting char
|
||||
|
||||
swprintf(buffer, BUF_SIZE, u"%S", "Hello"); // GOOD
|
||||
swprintf(buffer, BUF_SIZE, u"%S", u"Hello"); // BAD: expecting char
|
||||
swprintf(buffer, BUF_SIZE, u"%S", L"Hello"); // BAD: expecting char
|
||||
swprintf(buffer, BUF_SIZE, u"%S", "Hello"); // BAD: expecting char16_t [NOT DETECTED]
|
||||
swprintf(buffer, BUF_SIZE, u"%S", u"Hello"); // GOOD
|
||||
swprintf(buffer, BUF_SIZE, u"%S", L"Hello"); // BAD: expecting char16_t [NOT DETECTED]
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
| printf.cpp:33:31:33:37 | test | This argument should be of type 'char *' but is of type 'char16_t *' |
|
||||
| printf.cpp:45:29:45:35 | test | This argument should be of type 'char *' but is of type 'char16_t *' |
|
||||
| printf.cpp:52:29:52:35 | test | This argument should be of type 'char16_t *' but is of type 'wchar_t *' |
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| printf.cpp:15:5:15:12 | swprintf | char16_t | char | char16_t |
|
||||
| printf.cpp:15:5:15:12 | swprintf | char | char16_t | char16_t |
|
||||
| printf.cpp:26:5:26:11 | sprintf | char | char16_t | char16_t |
|
||||
|
||||
@@ -30,7 +30,7 @@ int sprintf(char *dest, char *format, ...);
|
||||
void test1() {
|
||||
WCHAR string[20];
|
||||
|
||||
swprintf(string, u"test %s", u"test"); // GOOD
|
||||
swprintf(string, u"test %s", u"test"); // BAD: `char16_t` string parameter read as `char` string
|
||||
}
|
||||
|
||||
void test2() {
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
|
||||
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
|
||||
| printf1.h:47:19:47:21 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long' |
|
||||
| printf1.h:125:18:125:18 | c | This argument should be of type 'wchar_t *' but is of type 'char *' |
|
||||
| printf1.h:128:18:128:19 | wc | This argument should be of type 'char *' but is of type 'wchar_t *' |
|
||||
| printf1.h:126:18:126:19 | wc | This argument should be of type 'char *' but is of type 'wchar_t *' |
|
||||
| printf1.h:127:18:127:18 | c | This argument should be of type 'wchar_t *' but is of type 'char *' |
|
||||
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *' |
|
||||
| real_world.h:62:22:62:23 | & ... | This argument should be of type 'short *' but is of type 'int *' |
|
||||
| real_world.h:63:22:63:24 | & ... | This argument should be of type 'short *' but is of type 'unsigned int *' |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
| common.h:12:12:12:17 | printf | char | wchar_t | wchar_t |
|
||||
| common.h:15:12:15:18 | wprintf | wchar_t | char | wchar_t |
|
||||
| common.h:15:12:15:18 | wprintf | char | wchar_t | wchar_t |
|
||||
| format.h:4:13:4:17 | error | char | wchar_t | wchar_t |
|
||||
| real_world.h:8:12:8:18 | fprintf | char | wchar_t | wchar_t |
|
||||
| real_world.h:33:6:33:12 | msg_out | char | wchar_t | wchar_t |
|
||||
|
||||
@@ -122,8 +122,8 @@ void test_chars(char c, wchar_t wc, wint_t wt)
|
||||
|
||||
void test_ws(char *c, wchar_t *wc)
|
||||
{
|
||||
wprintf(L"%s", c); // GOOD [FALSE POSITIVE]
|
||||
wprintf(L"%s", wc); // BAD [NOT DETECTED]
|
||||
wprintf(L"%S", c); // BAD [NOT DETECTED]
|
||||
wprintf(L"%S", wc); // GOOD [FALSE POSITIVE]
|
||||
wprintf(L"%s", c); // GOOD
|
||||
wprintf(L"%s", wc); // BAD
|
||||
wprintf(L"%S", c); // BAD
|
||||
wprintf(L"%S", wc); // GOOD
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
| printf1.h:74:19:74:22 | C_ST | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
|
||||
| printf1.h:75:19:75:28 | sizeof(<expr>) | This argument should be of type 'ssize_t' but is of type 'unsigned long long' |
|
||||
| printf1.h:84:23:84:35 | ... - ... | This argument should be of type 'ssize_t' but is of type 'long long' |
|
||||
| printf1.h:125:18:125:18 | c | This argument should be of type '__wchar_t *' but is of type 'char *' |
|
||||
| printf1.h:128:18:128:19 | wc | This argument should be of type 'char *' but is of type '__wchar_t *' |
|
||||
| printf1.h:126:18:126:19 | wc | This argument should be of type 'char *' but is of type '__wchar_t *' |
|
||||
| printf1.h:127:18:127:18 | c | This argument should be of type '__wchar_t *' but is of type 'char *' |
|
||||
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *' |
|
||||
| real_world.h:62:22:62:23 | & ... | This argument should be of type 'short *' but is of type 'int *' |
|
||||
| real_world.h:63:22:63:24 | & ... | This argument should be of type 'short *' but is of type 'unsigned int *' |
|
||||
|
||||
@@ -123,7 +123,7 @@ void test_chars(char c, wchar_t wc, wint_t wt)
|
||||
void test_ws(char *c, wchar_t *wc, wint_t *wt)
|
||||
{
|
||||
wprintf(L"%s", c); // BAD [NOT DETECTED]
|
||||
wprintf(L"%s", wc); // GOOD
|
||||
wprintf(L"%S", c); // GOOD
|
||||
wprintf(L"%s", wc); // GOOD [FALSE POSITIVE]
|
||||
wprintf(L"%S", c); // GOOD [FALSE POSITIVE]
|
||||
wprintf(L"%S", wc); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user