Merge branch 'main' into rdmarsh2/cpp/output-iterators-2

Resolve merge conflict in tests
This commit is contained in:
Robert Marsh
2020-10-23 13:50:15 -07:00
115 changed files with 8830 additions and 444 deletions

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* The `cpp/wrong-type-format-argument` and `cpp/non-portable-printf` queries have been hardened so that they do not produce nonsensical results on databases that contain errors (specifically the `ErroneousType`).

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* The 'Not enough memory allocated for pointer type' (cpp/allocation-too-small) and 'Not enough memory allocated for array of pointer type' (cpp/suspicious-allocation-size) queries have been improved. Previously some allocations would be reported by both queries, this no longer occurs. In addition more allocation functions are now understood by both queries.

View File

@@ -13,30 +13,9 @@
*/
import cpp
import semmle.code.cpp.models.Models
class Allocation extends FunctionCall {
Allocation() {
exists(string name |
this.getTarget().hasGlobalOrStdName(name) and
(name = "malloc" or name = "calloc" or name = "realloc")
)
}
private string getName() { this.getTarget().hasGlobalOrStdName(result) }
int getSize() {
this.getName() = "malloc" and
this.getArgument(0).getValue().toInt() = result
or
this.getName() = "realloc" and
this.getArgument(1).getValue().toInt() = result
or
this.getName() = "calloc" and
result = this.getArgument(0).getValue().toInt() * this.getArgument(1).getValue().toInt()
}
}
predicate baseType(Allocation alloc, Type base) {
predicate baseType(AllocationExpr alloc, Type base) {
exists(PointerType pointer |
pointer.getBaseType() = base and
(
@@ -54,11 +33,12 @@ predicate decideOnSize(Type t, int size) {
size = min(t.getSize())
}
from Allocation alloc, Type base, int basesize, int allocated
from AllocationExpr alloc, Type base, int basesize, int allocated
where
baseType(alloc, base) and
allocated = alloc.getSize() and
allocated = alloc.getSizeBytes() and
decideOnSize(base, basesize) and
alloc.(FunctionCall).getTarget() instanceof AllocationFunction and // exclude `new` and similar
basesize > allocated
select alloc,
"Type '" + base.getName() + "' is " + basesize.toString() + " bytes, but only " +

View File

@@ -13,25 +13,9 @@
*/
import cpp
import semmle.code.cpp.models.Models
class Allocation extends FunctionCall {
Allocation() { this.getTarget().hasGlobalOrStdName(["malloc", "calloc", "realloc"]) }
private string getName() { this.getTarget().hasGlobalOrStdName(result) }
int getSize() {
this.getName() = "malloc" and
this.getArgument(0).getValue().toInt() = result
or
this.getName() = "realloc" and
this.getArgument(1).getValue().toInt() = result
or
this.getName() = "calloc" and
result = this.getArgument(0).getValue().toInt() * this.getArgument(1).getValue().toInt()
}
}
predicate baseType(Allocation alloc, Type base) {
predicate baseType(AllocationExpr alloc, Type base) {
exists(PointerType pointer |
pointer.getBaseType() = base and
(
@@ -44,16 +28,23 @@ predicate baseType(Allocation alloc, Type base) {
)
}
from Allocation alloc, Type base, int basesize, int allocated
predicate decideOnSize(Type t, int size) {
// If the codebase has more than one type with the same name, it can have more than one size.
size = min(t.getSize())
}
from AllocationExpr alloc, Type base, int basesize, int allocated
where
baseType(alloc, base) and
allocated = alloc.getSize() and
allocated = alloc.getSizeBytes() and
decideOnSize(base, basesize) and
alloc.(FunctionCall).getTarget() instanceof AllocationFunction and // exclude `new` and similar
// If the codebase has more than one type with the same name, check if any matches
not exists(int size | base.getSize() = size |
size = 0 or
(allocated / size) * size = allocated
) and
basesize = min(base.getSize())
not basesize > allocated // covered by SizeCheck.ql
select alloc,
"Allocated memory (" + allocated.toString() + " bytes) is not a multiple of the size of '" +
base.getName() + "' (" + basesize.toString() + " bytes)."

View File

@@ -155,7 +155,8 @@ where
not actual.getUnspecifiedType().(IntegralType).getSize() = sizeof_IntType()
) and
not arg.isAffectedByMacro() and
not arg.isFromUninstantiatedTemplate(_)
not arg.isFromUninstantiatedTemplate(_) and
not actual.getUnspecifiedType() instanceof ErroneousType
select arg,
"This argument should be of type '" + expected.getName() + "' but is of type '" +
actual.getUnspecifiedType().getName() + "'"

View File

@@ -88,7 +88,8 @@ where
not arg.isAffectedByMacro() and
size32 = ilp32.paddedSize(actual) and
size64 = lp64.paddedSize(actual) and
size64 != size32
size64 != size32 and
not actual instanceof ErroneousType
select arg,
"This argument should be of type '" + expected.getName() + "' but is of type '" + actual.getName()
+ "' (which changes size from " + size32 + " to " + size64 + " on 64-bit systems)."

View File

@@ -1,4 +1,17 @@
import cpp
private import PrintAST
/**
* Print function declarations only if there is a `PrintASTConfiguration`
* that requests that function, or no `PrintASTConfiguration` exists.
*/
private predicate shouldPrintDeclaration(Declaration decl) {
not decl instanceof Function
or
not exists(PrintASTConfiguration c)
or
exists(PrintASTConfiguration config | config.shouldPrintFunction(decl))
}
/**
* Gets a string containing the scope in which this declaration is declared.
@@ -48,6 +61,8 @@ private string getTemplateArgumentString(Declaration d, int i) {
* A `Declaration` extended to add methods for generating strings useful only for dumps and debugging.
*/
abstract private class DumpDeclaration extends Declaration {
DumpDeclaration() { shouldPrintDeclaration(this) }
/**
* Gets a string that uniquely identifies this declaration, suitable for use when debugging queries. Only holds for
* functions, user-defined types, global and namespace-scope variables, and member variables.

View File

@@ -7208,3 +7208,52 @@
| vector.cpp:449:6:449:7 | it | vector.cpp:449:4:449:4 | call to operator++ | |
| vector.cpp:449:11:449:16 | call to source | vector.cpp:449:3:449:3 | ref arg call to operator* | TAINT |
| vector.cpp:450:8:450:10 | ref arg out | vector.cpp:451:2:451:2 | out | |
| vector.cpp:467:22:467:25 | call to vector | vector.cpp:471:8:471:8 | v | |
| vector.cpp:467:22:467:25 | call to vector | vector.cpp:472:11:472:11 | v | |
| vector.cpp:467:22:467:25 | call to vector | vector.cpp:473:8:473:8 | v | |
| vector.cpp:467:22:467:25 | call to vector | vector.cpp:474:2:474:2 | v | |
| vector.cpp:468:11:468:16 | call to source | vector.cpp:472:18:472:18 | s | |
| vector.cpp:469:10:469:11 | 0 | vector.cpp:472:13:472:13 | i | |
| vector.cpp:471:8:471:8 | ref arg v | vector.cpp:472:11:472:11 | v | |
| vector.cpp:471:8:471:8 | ref arg v | vector.cpp:473:8:473:8 | v | |
| vector.cpp:471:8:471:8 | ref arg v | vector.cpp:474:2:474:2 | v | |
| vector.cpp:472:10:472:14 | & ... | vector.cpp:472:3:472:8 | call to memcpy | |
| vector.cpp:472:10:472:14 | ref arg & ... | vector.cpp:472:12:472:12 | call to operator[] [inner post update] | |
| vector.cpp:472:11:472:11 | ref arg v | vector.cpp:473:8:473:8 | v | |
| vector.cpp:472:11:472:11 | ref arg v | vector.cpp:474:2:474:2 | v | |
| vector.cpp:472:11:472:11 | v | vector.cpp:472:12:472:12 | call to operator[] | TAINT |
| vector.cpp:472:12:472:12 | call to operator[] | vector.cpp:472:10:472:14 | & ... | |
| vector.cpp:472:12:472:12 | call to operator[] [inner post update] | vector.cpp:472:11:472:11 | ref arg v | TAINT |
| vector.cpp:472:17:472:18 | & ... | vector.cpp:472:3:472:8 | call to memcpy | TAINT |
| vector.cpp:472:17:472:18 | & ... | vector.cpp:472:10:472:14 | ref arg & ... | TAINT |
| vector.cpp:472:18:472:18 | s | vector.cpp:472:10:472:14 | ref arg & ... | |
| vector.cpp:472:18:472:18 | s | vector.cpp:472:17:472:18 | & ... | |
| vector.cpp:473:8:473:8 | ref arg v | vector.cpp:474:2:474:2 | v | |
| vector.cpp:477:24:477:27 | call to vector | vector.cpp:483:8:483:9 | cs | |
| vector.cpp:477:24:477:27 | call to vector | vector.cpp:484:11:484:12 | cs | |
| vector.cpp:477:24:477:27 | call to vector | vector.cpp:486:8:486:9 | cs | |
| vector.cpp:477:24:477:27 | call to vector | vector.cpp:487:2:487:2 | cs | |
| vector.cpp:478:21:478:37 | call to source | vector.cpp:480:22:480:24 | src | |
| vector.cpp:478:21:478:37 | call to source | vector.cpp:482:8:482:10 | src | |
| vector.cpp:478:21:478:37 | call to source | vector.cpp:484:25:484:27 | src | |
| vector.cpp:478:21:478:37 | call to source | vector.cpp:485:8:485:10 | src | |
| vector.cpp:479:23:479:24 | 10 | vector.cpp:484:14:484:17 | offs | |
| vector.cpp:480:26:480:31 | call to length | vector.cpp:484:38:484:40 | len | |
| vector.cpp:482:8:482:10 | ref arg src | vector.cpp:484:25:484:27 | src | |
| vector.cpp:482:8:482:10 | ref arg src | vector.cpp:485:8:485:10 | src | |
| vector.cpp:483:8:483:9 | ref arg cs | vector.cpp:484:11:484:12 | cs | |
| vector.cpp:483:8:483:9 | ref arg cs | vector.cpp:486:8:486:9 | cs | |
| vector.cpp:483:8:483:9 | ref arg cs | vector.cpp:487:2:487:2 | cs | |
| vector.cpp:484:10:484:22 | & ... | vector.cpp:484:3:484:8 | call to memcpy | |
| vector.cpp:484:10:484:22 | ref arg & ... | vector.cpp:484:13:484:13 | call to operator[] [inner post update] | |
| vector.cpp:484:11:484:12 | cs | vector.cpp:484:13:484:13 | call to operator[] | TAINT |
| vector.cpp:484:11:484:12 | ref arg cs | vector.cpp:486:8:486:9 | cs | |
| vector.cpp:484:11:484:12 | ref arg cs | vector.cpp:487:2:487:2 | cs | |
| vector.cpp:484:13:484:13 | call to operator[] | vector.cpp:484:10:484:22 | & ... | |
| vector.cpp:484:13:484:13 | call to operator[] [inner post update] | vector.cpp:484:11:484:12 | ref arg cs | TAINT |
| vector.cpp:484:14:484:17 | offs | vector.cpp:484:14:484:21 | ... + ... | TAINT |
| vector.cpp:484:21:484:21 | 1 | vector.cpp:484:14:484:21 | ... + ... | TAINT |
| vector.cpp:484:25:484:27 | src | vector.cpp:484:29:484:33 | call to c_str | TAINT |
| vector.cpp:484:29:484:33 | call to c_str | vector.cpp:484:3:484:8 | call to memcpy | TAINT |
| vector.cpp:484:29:484:33 | call to c_str | vector.cpp:484:10:484:22 | ref arg & ... | TAINT |
| vector.cpp:486:8:486:9 | ref arg cs | vector.cpp:487:2:487:2 | cs | |

View File

@@ -192,7 +192,7 @@ void *memcpy(void *dest, void *src, int len);
void test_memcpy(int *source) {
int x;
memcpy(&x, source, sizeof(int));
sink(x);
sink(x); // tainted
}
// --- std::swap ---

View File

@@ -662,3 +662,7 @@
| vector.cpp:436:8:436:10 | out | vector.cpp:435:11:435:16 | call to source |
| vector.cpp:443:8:443:10 | out | vector.cpp:417:33:417:45 | source_string |
| vector.cpp:450:8:450:10 | out | vector.cpp:449:11:449:16 | call to source |
| vector.cpp:473:8:473:8 | v | vector.cpp:468:11:468:16 | call to source |
| vector.cpp:482:8:482:10 | src | vector.cpp:478:21:478:37 | call to source |
| vector.cpp:485:8:485:10 | src | vector.cpp:478:21:478:37 | call to source |
| vector.cpp:486:8:486:9 | cs | vector.cpp:478:21:478:37 | call to source |

View File

@@ -388,3 +388,5 @@
| vector.cpp:436:8:436:10 | vector.cpp:435:11:435:16 | AST only |
| vector.cpp:443:8:443:10 | vector.cpp:417:33:417:45 | AST only |
| vector.cpp:450:8:450:10 | vector.cpp:449:11:449:16 | AST only |
| vector.cpp:473:8:473:8 | vector.cpp:468:11:468:16 | AST only |
| vector.cpp:486:8:486:9 | vector.cpp:478:21:478:37 | AST only |

View File

@@ -416,3 +416,5 @@
| vector.cpp:312:7:312:7 | Argument 0 indirection | vector.cpp:303:14:303:19 | call to source |
| vector.cpp:324:7:324:8 | Argument 0 indirection | vector.cpp:318:15:318:20 | call to source |
| vector.cpp:326:7:326:8 | Argument 0 indirection | vector.cpp:318:15:318:20 | call to source |
| vector.cpp:482:8:482:10 | Argument 0 indirection | vector.cpp:478:21:478:37 | call to source |
| vector.cpp:485:8:485:10 | Argument 0 indirection | vector.cpp:478:21:478:37 | call to source |

View File

@@ -450,3 +450,39 @@ void test_vector_inserter(char *source_string) {
sink(out); // tainted [NOT DETECTED by IR]
}
}
void *memcpy(void *s1, const void *s2, size_t n);
namespace ns_string
{
std::string source();
}
void sink(std::vector<char> &);
void sink(std::string &);
void test_vector_memcpy()
{
{
std::vector<int> v(100);
int s = source();
int i = 0;
sink(v);
memcpy(&v[i], &s, sizeof(int));
sink(v); // tainted [NOT DETECTED by IR]
}
{
std::vector<char> cs(100);
std::string src = ns_string::source();
const size_t offs = 10;
const size_t len = src.length();
sink(src); // tainted
sink(cs);
memcpy(&cs[offs + 1], src.c_str(), len);
sink(src); // tainted
sink(cs); // tainted [NOT DETECTED by IR]
}
}

View File

@@ -2,3 +2,4 @@
| test.c:17:20:17:25 | call to malloc | Type 'double' is 8 bytes, but only 5 bytes are allocated. |
| test.c:32:19:32:24 | call to malloc | Type 'float' is 4 bytes, but only 2 bytes are allocated. |
| test.c:33:20:33:25 | call to malloc | Type 'double' is 8 bytes, but only 4 bytes are allocated. |
| test.c:59:15:59:20 | call to malloc | Type 'MyUnion' is 128 bytes, but only 8 bytes are allocated. |

View File

@@ -0,0 +1,4 @@
| test2.c:16:23:16:28 | call to malloc | Allocated memory (27 bytes) is not a multiple of the size of 'long long' (8 bytes). |
| test2.c:17:20:17:25 | call to malloc | Allocated memory (33 bytes) is not a multiple of the size of 'double' (8 bytes). |
| test2.c:32:23:32:28 | call to malloc | Allocated memory (28 bytes) is not a multiple of the size of 'long long' (8 bytes). |
| test2.c:33:20:33:25 | call to malloc | Allocated memory (20 bytes) is not a multiple of the size of 'double' (8 bytes). |

View File

@@ -43,5 +43,18 @@ void good1(void) {
free(dptr);
}
typedef struct _myStruct
{
int x, y;
} MyStruct;
typedef union _myUnion
{
MyStruct ms;
char data[128];
} MyUnion;
void test_union() {
MyUnion *a = malloc(sizeof(MyUnion)); // GOOD
MyUnion *b = malloc(sizeof(MyStruct)); // BAD (too small)
}

View File

@@ -0,0 +1,6 @@
int i = 2000000000;
long j = i * i; // BAD
long k = (long) i * i; // GOOD
long l = (long) (i * i); // permitted as the conversion is explicit
long m = static_cast<long> (i) * i; // GOOD
long n = static_cast<long> (i * i); // permitted as the conversion is explicit

View File

@@ -12,3 +12,4 @@
| IntMultToLong.c:108:14:108:78 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'unsigned long'. |
| IntMultToLong.c:119:14:119:26 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'unsigned long'. |
| IntMultToLong.c:126:14:126:32 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'unsigned long'. |
| IntMultToLong.cpp:2:10:2:14 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'long'. |

View File

@@ -3,18 +3,19 @@
| nested.cpp:21:23:21:26 | fmt0 | The format string argument to snprintf should be constant to prevent security issues and other potential errors. |
| nested.cpp:79:32:79:38 | call to get_fmt | The format string argument to diagnostic should be constant to prevent security issues and other potential errors. |
| nested.cpp:87:18:87:20 | fmt | The format string argument to diagnostic should be constant to prevent security issues and other potential errors. |
| test.cpp:48:10:48:21 | call to make_message | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:54:12:54:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:57:12:57:21 | call to const_wash | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:58:12:58:26 | ... + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:59:12:59:17 | + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:60:12:60:18 | * ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:61:12:61:18 | & ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:62:12:62:39 | ... + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:64:10:64:35 | ... + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:67:12:67:20 | ... + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:73:12:73:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:79:12:79:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:85:12:85:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:90:12:90:18 | ++ ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:107:12:107:24 | new[] | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:50:10:50:21 | call to make_message | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:56:12:56:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:59:12:59:21 | call to const_wash | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:60:12:60:26 | ... + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:61:12:61:17 | + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:62:12:62:18 | * ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:63:12:63:18 | & ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:64:12:64:39 | ... + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:66:10:66:35 | ... + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:69:12:69:20 | ... + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:75:12:75:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:81:12:81:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:87:12:87:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:92:12:92:18 | ++ ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:109:12:109:24 | new[] | The format string argument to printf should be constant to prevent security issues and other potential errors. |
| test.cpp:129:20:129:26 | access to array | The format string argument to sprintf should be constant to prevent security issues and other potential errors. |

View File

@@ -2,6 +2,8 @@ extern "C" int printf(const char *fmt, ...);
extern "C" int sprintf(char *buf, const char *fmt, ...);
extern "C" char *gettext (const char *);
#define MYSPRINTF sprintf
bool gettext_debug = false;
const char *messages[] = {
@@ -119,6 +121,13 @@ int main(int argc, char **argv) {
//
//
printf(const_wash("Hello, World\n")); // GOOD
{
char buffer[1024];
MYSPRINTF(buffer, "constant"); // GOOD
MYSPRINTF(buffer, argv[0]); // BAD
}
}
const char *simple_func(const char *str) {

View File

@@ -1,4 +0,0 @@
| test.c:16:23:16:28 | call to malloc | Allocated memory (27 bytes) is not a multiple of the size of 'long long' (8 bytes). |
| test.c:17:20:17:25 | call to malloc | Allocated memory (33 bytes) is not a multiple of the size of 'double' (8 bytes). |
| test.c:32:23:32:28 | call to malloc | Allocated memory (28 bytes) is not a multiple of the size of 'long long' (8 bytes). |
| test.c:33:20:33:25 | call to malloc | Allocated memory (20 bytes) is not a multiple of the size of 'double' (8 bytes). |