Merge branch 'master' into master

This commit is contained in:
Raul Garcia
2018-09-25 10:58:51 -07:00
committed by GitHub
328 changed files with 8737 additions and 7968 deletions

View File

@@ -1,2 +1,2 @@
[*.{ql,qll,qlref,dbscheme,qhelp,html,js,mjs,ts,json,yml}] [*]
end_of_line = lf end_of_line = lf

63
.gitattributes vendored
View File

@@ -1,23 +1,48 @@
# The following file types will be normalized to LF line endings in the Git # Text files will be normalized to LF line endings in the Git database, and will keep those LF line
# database, and will keep those LF line endings in the working tree even on # endings in the working tree even on Windows. If you make changes below, you should renormalize the
# Windows. Any other files will have whatever line endings they had when they # affected files by running the following from the root of this repo (requires Git 2.16 or greater):
# were committed. If you add new entries below, you should renormalize the
# affected files by running the following from the root of this repo (requires
# Git 2.16 or greater):
# #
# git add --renormalize . # git add --renormalize .
# git status [just to show what files were renormalized] # git status [just to show what files were renormalized]
# git commit -m "Normalize line endings" # git commit -m "Normalize line endings"
#
# Also, please update .editorconfig to handle any new entries as well. # Anything Git auto-detects as text gets normalized and checked out as LF
*.ql eol=lf * text=auto eol=lf
*.qll eol=lf
*.qlref eol=lf # Explicitly set a bunch of known extensions to text, in case auto detection gets confused.
*.dbscheme eol=lf *.ql text
*.qhelp eol=lf *.qll text
*.html eol=lf *.qlref text
*.js eol=lf *.dbscheme text
*.mjs eol=lf *.qhelp text
*.ts eol=lf *.html text
*.json eol=lf *.htm text
*.yml eol=lf *.xhtml text
*.xhtm text
*.js text
*.mjs text
*.ts text
*.json text
*.yml text
*.yaml text
*.c text
*.cpp text
*.h text
*.hpp text
*.md text
*.stats text
*.xml text
*.sh text
*.pl text
*.java text
*.cs text
*.py text
*.lua text
*.expected text
# Explicitly set a bunch of known extensions to binary, because Git < 2.10 will treat
# `* text=auto eol=lf` as `* text eol=lf`
*.png -text
*.jpg -text
*.jpeg -text
*.gif -text

4
.gitignore vendored
View File

@@ -12,6 +12,4 @@
/.vs/ql/v15/Browse.VC.opendb /.vs/ql/v15/Browse.VC.opendb
/.vs/ql/v15/Browse.VC.db /.vs/ql/v15/Browse.VC.db
/.vs/ProjectSettings.json /.vs/ProjectSettings.json
/.vs/ql5/v15/Browse.VC.opendb
/.vs/ql5/v15/Browse.VC.db
/.vs/ql5/v15/.suo

View File

@@ -1,20 +1,20 @@
# Improvements to C/C++ analysis # Improvements to C/C++ analysis
## General improvements ## General improvements
## New queries ## New queries
| **Query** | **Tags** | **Purpose** | | **Query** | **Tags** | **Purpose** |
|-----------------------------|-----------|--------------------------------------------------------------------| |-----------------------------|-----------|--------------------------------------------------------------------|
| *@name of query (Query ID)* | *Tags* |*Aim of the new query and whether it is enabled by default or not* | | *@name of query (Query ID)* | *Tags* |*Aim of the new query and whether it is enabled by default or not* |
## Changes to existing queries ## Changes to existing queries
| **Query** | **Expected impact** | **Change** | | **Query** | **Expected impact** | **Change** |
|----------------------------|------------------------|------------------------------------------------------------------| |----------------------------|------------------------|------------------------------------------------------------------|
| *@name of query (Query ID)*| *Impact on results* | *How/why the query has changed* | | Resource not released in destructor | Fewer false positive results | Placement new is now excluded from the query. |
## Changes to QL libraries ## Changes to QL libraries
* Added a hash consing library for structural comparison of expressions. * Added a hash consing library for structural comparison of expressions.

View File

@@ -22,5 +22,6 @@
| Regular expression injection | Fewer false-positive results | This rule now identifies calls to `String.prototype.search` with more precision. | | Regular expression injection | Fewer false-positive results | This rule now identifies calls to `String.prototype.search` with more precision. |
| Unbound event handler receiver | Fewer false-positive results | This rule now recognizes additional ways class methods can be bound. | | Unbound event handler receiver | Fewer false-positive results | This rule now recognizes additional ways class methods can be bound. |
| Remote property injection | Fewer results | The precision of this rule has been revised to "medium". Results are no longer shown on LGTM by default. | | Remote property injection | Fewer results | The precision of this rule has been revised to "medium". Results are no longer shown on LGTM by default. |
| Missing CSRF middleware | Fewer false-positive results | This rule now recognizes additional CSRF protection middlewares. |
## Changes to QL libraries ## Changes to QL libraries

View File

@@ -1,13 +1,13 @@
# CWE-120: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow') # CWE-120: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
+ semmlecode-cpp-queries/Security/CWE/CWE-120/UnboundedWrite.ql: /CWE/CWE-120 + semmlecode-cpp-queries/Security/CWE/CWE-120/UnboundedWrite.ql: /CWE/CWE-120
@name Unbounded write (CWE-120) @name Unbounded write (CWE-120)
+ semmlecode-cpp-queries/Security/CWE/CWE-120/BadlyBoundedWrite.ql: /CWE/CWE-120 + semmlecode-cpp-queries/Security/CWE/CWE-120/BadlyBoundedWrite.ql: /CWE/CWE-120
@name Badly bounded write (CWE-120) @name Badly bounded write (CWE-120)
+ semmlecode-cpp-queries/Security/CWE/CWE-120/OverrunWrite.ql: /CWE/CWE-120 + semmlecode-cpp-queries/Security/CWE/CWE-120/OverrunWrite.ql: /CWE/CWE-120
@name Potentially overrunning write (CWE-120) @name Potentially overrunning write (CWE-120)
+ semmlecode-cpp-queries/Security/CWE/CWE-120/OverrunWriteFloat.ql: /CWE/CWE-120 + semmlecode-cpp-queries/Security/CWE/CWE-120/OverrunWriteFloat.ql: /CWE/CWE-120
@name Potentially overrunning write with float to string conversion (CWE-120) @name Potentially overrunning write with float to string conversion (CWE-120)
+ semmlecode-cpp-queries/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql: /CWE/CWE-120 + semmlecode-cpp-queries/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql: /CWE/CWE-120
@name Array offset used before range check (CWE-120) @name Array offset used before range check (CWE-120)
+ semmlecode-cpp-queries/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql: /CWE/CWE-120 + semmlecode-cpp-queries/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql: /CWE/CWE-120
@name Potentially unsafe use of strcat (CWE-120) @name Potentially unsafe use of strcat (CWE-120)

View File

@@ -1,3 +1,3 @@
# CWE-121: Stack-based Buffer Overflow # CWE-121: Stack-based Buffer Overflow
+ semmlecode-cpp-queries/Security/CWE/CWE-121/UnterminatedVarargsCall.ql: /CWE/CWE-121 + semmlecode-cpp-queries/Security/CWE/CWE-121/UnterminatedVarargsCall.ql: /CWE/CWE-121
@name Unterminated variadic call (CWE-121) @name Unterminated variadic call (CWE-121)

View File

@@ -1,7 +1,7 @@
# CWE-131: Incorrect Calculation of Buffer Size # CWE-131: Incorrect Calculation of Buffer Size
+ semmlecode-cpp-queries/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql: /CWE/CWE-131 + semmlecode-cpp-queries/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql: /CWE/CWE-131
@name No space for zero terminator (CWE-131) @name No space for zero terminator (CWE-131)
+ semmlecode-cpp-queries/Critical/SizeCheck.ql: /CWE/CWE-131 + semmlecode-cpp-queries/Critical/SizeCheck.ql: /CWE/CWE-131
@name Not enough memory allocated for pointer type (CWE-131) @name Not enough memory allocated for pointer type (CWE-131)
+ semmlecode-cpp-queries/Critical/SizeCheck2.ql: /CWE/CWE-131 + semmlecode-cpp-queries/Critical/SizeCheck2.ql: /CWE/CWE-131
@name Not enough memory allocated for array of pointer type (CWE-131) @name Not enough memory allocated for array of pointer type (CWE-131)

View File

@@ -1,13 +1,13 @@
# CWE-134: Uncontrolled Format String # CWE-134: Uncontrolled Format String
+ semmlecode-cpp-queries/Likely Bugs/Format/NonConstantFormat.ql: /CWE/CWE-134 + semmlecode-cpp-queries/Likely Bugs/Format/NonConstantFormat.ql: /CWE/CWE-134
@name Non-constant format string (CWE-134) @name Non-constant format string (CWE-134)
# This one runs out of memory. See ODASA-608. # This one runs out of memory. See ODASA-608.
#+ semmlecode-cpp-queries/PointsTo/TaintedFormatStrings.ql: /CWE/CWE-134 #+ semmlecode-cpp-queries/PointsTo/TaintedFormatStrings.ql: /CWE/CWE-134
+ semmlecode-cpp-queries/Likely Bugs/Format/WrongNumberOfFormatArguments.ql: /CWE/CWE-134 + semmlecode-cpp-queries/Likely Bugs/Format/WrongNumberOfFormatArguments.ql: /CWE/CWE-134
@name Wrong number of arguments to formatting function (CWE-134) @name Wrong number of arguments to formatting function (CWE-134)
+ semmlecode-cpp-queries/Likely Bugs/Format/WrongTypeFormatArguments.ql: /CWE/CWE-134 + semmlecode-cpp-queries/Likely Bugs/Format/WrongTypeFormatArguments.ql: /CWE/CWE-134
@name Wrong type of arguments to formatting function (CWE-134) @name Wrong type of arguments to formatting function (CWE-134)
+ semmlecode-cpp-queries/Security/CWE/CWE-134/UncontrolledFormatString.ql: /CWE/CWE-134 + semmlecode-cpp-queries/Security/CWE/CWE-134/UncontrolledFormatString.ql: /CWE/CWE-134
@name Uncontrolled format string (CWE-134) @name Uncontrolled format string (CWE-134)
+ semmlecode-cpp-queries/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql: /CWE/CWE-134 + semmlecode-cpp-queries/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql: /CWE/CWE-134
@name Uncontrolled format string (through global variable) (CWE-134) @name Uncontrolled format string (through global variable) (CWE-134)

View File

@@ -1,17 +1,17 @@
// an include declaration just adds one source dependency, it does not automatically // an include declaration just adds one source dependency, it does not automatically
// add a dependency from this file to all the declarations in stdio.h // add a dependency from this file to all the declarations in stdio.h
#include <stdio.h> #include <stdio.h>
#include <myfile.h> // contains non-static global myfile_err #include <myfile.h> // contains non-static global myfile_err
extern int myfile_err; // this external declaration adds a dependency on myfile.h extern int myfile_err; // this external declaration adds a dependency on myfile.h
class C { class C {
public: public:
C() { C() {
// one dependency for printf: // one dependency for printf:
printf("Hello world!"); printf("Hello world!");
// one dependency for FILE type, and one for NULL macro: // one dependency for FILE type, and one for NULL macro:
FILE fp = NULL; FILE fp = NULL;
} }
}; };

View File

@@ -1,20 +1,20 @@
//This struct contains 30 fields. //This struct contains 30 fields.
struct MyParticle { struct MyParticle {
bool isActive; bool isActive;
int priority; int priority;
float x, y, z; float x, y, z;
float dx, dy, dz; float dx, dy, dz;
float ddx, ddy, ddz; float ddx, ddy, ddz;
bool isCollider; bool isCollider;
int age, maxAge; int age, maxAge;
float size1, size2; float size1, size2;
bool hasColor; bool hasColor;
unsigned char r1, g1, b1, a1; unsigned char r1, g1, b1, a1;
unsigned char r2, g2, b2, a2; unsigned char r2, g2, b2, a2;
class texture *tex; class texture *tex;
float u1, v1, u2, v2; float u1, v1, u2, v2;
}; };

View File

@@ -1,8 +1,8 @@
// this example has 15 parameters. // this example has 15 parameters.
void fillRect(int x, int y, int w, int h, void fillRect(int x, int y, int w, int h,
int r1, int g1, int b1, int a1, int r1, int g1, int b1, int a1,
int r2, int g2, int b2, int a2, int r2, int g2, int b2, int a2,
gradient_type grad, unsigned int flags, bool border) gradient_type grad, unsigned int flags, bool border)
{ {
// ... // ...
} }

View File

@@ -1,13 +1,13 @@
//This condition is too complex and can be improved by using local variables //This condition is too complex and can be improved by using local variables
bool accept_message = bool accept_message =
(message_type == CONNECT && _state != CONNECTED) || (message_type == CONNECT && _state != CONNECTED) ||
(message_type == DISCONNECT && _state == CONNECTED) || (message_type == DISCONNECT && _state == CONNECTED) ||
(message_type == DATA && _state == CONNECTED); (message_type == DATA && _state == CONNECTED);
//This condition is acceptable, as all the logical operators are of the same type (&&) //This condition is acceptable, as all the logical operators are of the same type (&&)
bool valid_connect = bool valid_connect =
message_type == CONNECT && message_type == CONNECT &&
_state != CONNECTED && _state != CONNECTED &&
time_since_prev_connect > MAX_CONNECT_INTERVAL && time_since_prev_connect > MAX_CONNECT_INTERVAL &&
message_length <= MAX_PACKET_SIZE && message_length <= MAX_PACKET_SIZE &&
checksum(message) == get_checksum_field(message); checksum(message) == get_checksum_field(message);

View File

@@ -1,6 +1,6 @@
void f(int i) { void f(int i) {
for (int i = 0; i < 10; ++i) { //the loop variable hides the parameter to f() for (int i = 0; i < 10; ++i) { //the loop variable hides the parameter to f()
... ...
} }
} }

View File

@@ -1,12 +1,12 @@
void f() { void f() {
int i = 10; int i = 10;
for (int i = 0; i < 10; i++) { //the loop counter hides the variable for (int i = 0; i < 10; i++) { //the loop counter hides the variable
... ...
} }
{ {
int i = 12; //this variable hides the variable in the outer block int i = 12; //this variable hides the variable in the outer block
... ...
} }
} }

View File

@@ -1,12 +1,12 @@
int i = 10; int i = 10;
void f() { void f() {
for (int i = 0; i < 10; i++) { //the loop counter hides the global variable i for (int i = 0; i < 10; i++) { //the loop counter hides the global variable i
... ...
} }
{ {
int i = 12; //this variable hides the global variable i int i = 12; //this variable hides the global variable i
... ...
} }
} }

View File

@@ -1,9 +1,9 @@
void f(int i) { void f(int i) {
if (i == 10); //empty then block if (i == 10); //empty then block
... //won't be part of the if statement ... //won't be part of the if statement
if (i == 12) { if (i == 12) {
... ...
} else { //empty else block, most likely a mistake } else { //empty else block, most likely a mistake
} }
} }

View File

@@ -1,43 +1,43 @@
static int idctr = 0; static int idctr = 0;
//Basic connection with id //Basic connection with id
class Connection { class Connection {
public: public:
int connId; int connId;
virtual void print_info() { virtual void print_info() {
cout << "id: " << connId << "\n"; cout << "id: " << connId << "\n";
} }
Connection() { Connection() {
connId = idctr++; connId = idctr++;
} }
}; };
//Adds counters, and an overriding print_info //Adds counters, and an overriding print_info
class MeteredConnection : public Connection { class MeteredConnection : public Connection {
public: public:
int txCtr; int txCtr;
int rxCtr; int rxCtr;
MeteredConnection() { MeteredConnection() {
txCtr = 0; txCtr = 0;
rxCtr = 0; rxCtr = 0;
} }
virtual void print_info() { virtual void print_info() {
cout << "id: " << connId << "\n" << "tx/rx: " << txCtr << "/" << rxCtr << "\n"; cout << "id: " << connId << "\n" << "tx/rx: " << txCtr << "/" << rxCtr << "\n";
} }
}; };
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
Connection conn; Connection conn;
MeteredConnection m_conn; MeteredConnection m_conn;
Connection curr_conn = conn; Connection curr_conn = conn;
curr_conn.print_info(); curr_conn.print_info();
curr_conn = m_conn; //Wrong: Derived MetricConnection assigned to Connection curr_conn = m_conn; //Wrong: Derived MetricConnection assigned to Connection
//variable, will slice off the counters and the overriding print_info //variable, will slice off the counters and the overriding print_info
curr_conn.print_info(); //Will not print the counters. curr_conn.print_info(); //Will not print the counters.
Connection* curr_pconn = &conn; Connection* curr_pconn = &conn;
curr_pconn->print_info(); curr_pconn->print_info();
curr_pconn = &m_conn; //Correct: Pointer assigned to address of the MetricConnection. curr_pconn = &m_conn; //Correct: Pointer assigned to address of the MetricConnection.
//Counters and virtual functions remain intact. //Counters and virtual functions remain intact.
curr_pconn->print_info(); //Will call the correct method MeteredConnection::print_info curr_pconn->print_info(); //Will call the correct method MeteredConnection::print_info
} }

View File

@@ -1,16 +1,16 @@
void sanitize(Fields[] record) { void sanitize(Fields[] record) {
//The number of fields here can be put in a const //The number of fields here can be put in a const
for (fieldCtr = 0; field < 7; field++) { for (fieldCtr = 0; field < 7; field++) {
sanitize(fields[fieldCtr]); sanitize(fields[fieldCtr]);
} }
} }
#define NUM_FIELDS 7 #define NUM_FIELDS 7
void process(Fields[] record) { void process(Fields[] record) {
//This avoids using a magic constant by using the macro instead //This avoids using a magic constant by using the macro instead
for (fieldCtr = 0; field < NUM_FIELDS; field++) { for (fieldCtr = 0; field < NUM_FIELDS; field++) {
process(fields[fieldCtr]); process(fields[fieldCtr]);
} }
} }

View File

@@ -1,26 +1,26 @@
class C { class C {
private: private:
Other* other = NULL; Other* other = NULL;
public: public:
C(const C& copyFrom) { C(const C& copyFrom) {
Other* newOther = new Other(); Other* newOther = new Other();
*newOther = copyFrom.other; *newOther = copyFrom.other;
this->other = newOther; this->other = newOther;
} }
//No operator=, by default will just copy the pointer other, will not create a new object //No operator=, by default will just copy the pointer other, will not create a new object
}; };
class D { class D {
Other* other = NULL; Other* other = NULL;
public: public:
D& operator=(D& rhs) { D& operator=(D& rhs) {
Other* newOther = new Other(); Other* newOther = new Other();
*newOther = rhs.other; *newOther = rhs.other;
this->other = newOther; this->other = newOther;
return *this; return *this;
} }
//No copy constructor, will just copy the pointer other and not create a new object //No copy constructor, will just copy the pointer other and not create a new object
}; };

View File

@@ -1,32 +1,32 @@
//This switch statement has long case statements, and can become difficult to //This switch statement has long case statements, and can become difficult to
//read as the processing for each message type becomes more complex //read as the processing for each message type becomes more complex
switch (message_type) { switch (message_type) {
case CONNECT: case CONNECT:
_state = CONNECTING; _state = CONNECTING;
int message_id = message_get_id(message); int message_id = message_get_id(message);
int source = connect_get_source(message); int source = connect_get_source(message);
//More code here... //More code here...
send(connect_response); send(connect_response);
break; break;
case DISCONNECT: case DISCONNECT:
_state = DISCONNECTING; _state = DISCONNECTING;
int message_id = message_get_id(message); int message_id = message_get_id(message);
int source = disconnect_get_source(message); int source = disconnect_get_source(message);
//More code here... //More code here...
send(disconnect_response); send(disconnect_response);
break; break;
default: default:
log("Invalid message, id : %d", message_get_id(message)); log("Invalid message, id : %d", message_get_id(message));
} }
//This is better, as each case is split out to a separate function //This is better, as each case is split out to a separate function
switch (packet_type) { switch (packet_type) {
case STREAM: case STREAM:
process_stream_packet(packet); process_stream_packet(packet);
break; break;
case DATAGRAM: case DATAGRAM:
process_datagram_packet(packet); process_datagram_packet(packet);
break; break;
default: default:
log("Invalid packet type: %d", packet_type); log("Invalid packet type: %d", packet_type);
} }

View File

@@ -1,5 +1,5 @@
{ {
int x = 0; //x is unused int x = 0; //x is unused
int y = 0; int y = 0;
cout << y; cout << y;
} }

View File

@@ -1,14 +1,14 @@
//start of file //start of file
static void f() { //static function f() is unused in the file static void f() { //static function f() is unused in the file
//... //...
} }
static void g() { static void g() {
//... //...
} }
void public_func() { //non-static function public_func is not called in file, void public_func() { //non-static function public_func is not called in file,
//but could be visible in other files //but could be visible in other files
//... //...
g(); //call to g() g(); //call to g()
//... //...
} }
//end of file //end of file

View File

@@ -1,5 +1,5 @@
void f() { void f() {
static int i = 0; //i is unused static int i = 0; //i is unused
... ...
return; return;
} }

View File

@@ -1,19 +1,19 @@
while(result) { while(result) {
if ( ... ) if ( ... )
... ...
else if (result //wrong: this test is redundant else if (result //wrong: this test is redundant
&& result->flags != 0) && result->flags != 0)
... ...
result = next(queue); result = next(queue);
} }
fp = fopen(log, "r"); fp = fopen(log, "r");
if (fp) { if (fp) {
/* /*
* large block of code * large block of code
*/ */
if (!fp) { //wrong: always false if (!fp) { //wrong: always false
... /* dead code */ ... /* dead code */
} }
} }

View File

@@ -1,12 +1,12 @@
class C { class C {
public: public:
void g() { void g() {
... ...
//f() was previously used but is now commented, orphaning f() //f() was previously used but is now commented, orphaning f()
//f(); //f();
... ...
} }
private: private:
void f() { //is now unused, and can be removed void f() { //is now unused, and can be removed
} }
}; };

View File

@@ -1,9 +1,9 @@
int f() { int f() {
try { try {
int sockfd = socket(AF_INET, SOCK_STREAM, 0); int sockfd = socket(AF_INET, SOCK_STREAM, 0);
do_stuff(sockfd); do_stuff(sockfd);
return sockfd; //if there are no exceptions, the socket is returned return sockfd; //if there are no exceptions, the socket is returned
} catch (int do_stuff_exception) { } catch (int do_stuff_exception) {
return -1; //return error value, but sockfd may still be open return -1; //return error value, but sockfd may still be open
} }
} }

View File

@@ -1,6 +1,6 @@
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
int sockfd = socket(AF_INET, SOCK_STREAM, 0); int sockfd = socket(AF_INET, SOCK_STREAM, 0);
int status = 0; int status = 0;
... //code that does not close sockfd ... //code that does not close sockfd
return status; //sockfd is never closed return status; //sockfd is never closed
} }

View File

@@ -1,11 +1,11 @@
int g_callCtr; int g_callCtr;
void initGlobals() { void initGlobals() {
g_callCtr = 0; g_callCtr = 0;
} }
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
... ...
cout << g_callCtr; //callCtr used before it is initialized cout << g_callCtr; //callCtr used before it is initialized
initGlobals(); initGlobals();
} }

View File

@@ -1,12 +1,12 @@
GlobalStorage *g_storage; GlobalStorage *g_storage;
void init() { //initializes g_storage, but is never run from main void init() { //initializes g_storage, but is never run from main
g_storage = new GlobalStorage(); g_storage = new GlobalStorage();
... ...
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
... //init not called ... //init not called
strcpy(g_storage->name, argv[1]); // g_storage is used before init() is called strcpy(g_storage->name, argv[1]); // g_storage is used before init() is called
... ...
} }

View File

@@ -1,13 +1,13 @@
typedef struct Names { typedef struct Names {
char first[100]; char first[100];
char last[100]; char last[100];
} Names; } Names;
int doFoo(Names n) { //wrong: n is passed by value (meaning the entire structure int doFoo(Names n) { //wrong: n is passed by value (meaning the entire structure
//is copied onto the stack, instead of just a pointer) //is copied onto the stack, instead of just a pointer)
... ...
} }
int doBar(Names &n) { //better, only a reference is passed int doBar(Names &n) { //better, only a reference is passed
... ...
} }

View File

@@ -1,11 +1,11 @@
typedef struct { typedef struct {
char name[100]; char name[100];
int status; int status;
} person; } person;
void f() { void f() {
person* buf = NULL; person* buf = NULL;
buf = malloc(sizeof(person)); buf = malloc(sizeof(person));
(*buf).status = 0; //access to buf before it was checked for NULL (*buf).status = 0; //access to buf before it was checked for NULL
} }

View File

@@ -1,5 +1,5 @@
Record* record = new Record[SIZE]; Record* record = new Record[SIZE];
... ...
delete record; //record was created using 'new[]', but was freed using 'delete' delete record; //record was created using 'new[]', but was freed using 'delete'

View File

@@ -1,5 +1,5 @@
Record *ptr = new Record(...); Record *ptr = new Record(...);
... ...
delete [] ptr; // ptr was created using 'new', but was freed using 'delete[]' delete [] ptr; // ptr was created using 'new', but was freed using 'delete[]'

View File

@@ -1,5 +1,5 @@
Record *ptr = new Record(...); Record *ptr = new Record(...);
... ...
free(ptr); // BAD: ptr was created using 'new', but is being freed using 'free' free(ptr); // BAD: ptr was created using 'new', but is being freed using 'free'

View File

@@ -1,6 +1,6 @@
{ {
int i; int i;
... ...
int g = COEFF * i; //i is used before it is initialized int g = COEFF * i; //i is used before it is initialized
} }

View File

@@ -1,13 +1,13 @@
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
char param[SIZE]; char param[SIZE];
char arg1[10]; char arg1[10];
char arg2[20]; char arg2[20];
//wrong: only uses the size of the source (argv[1]) when using strncpy //wrong: only uses the size of the source (argv[1]) when using strncpy
strncpy(param, argv[1], strlen(arg1)); strncpy(param, argv[1], strlen(arg1));
//correct: uses the size of the destination array as well //correct: uses the size of the destination array as well
strncpy(param, argv[1], min(strlen(arg1, sizeof(param) -1))); strncpy(param, argv[1], min(strlen(arg1, sizeof(param) -1)));
} }

View File

@@ -1,23 +1,23 @@
int doFoo() { int doFoo() {
... ...
return status; return status;
} }
void f() { void f() {
if (doFoo() == OK) { if (doFoo() == OK) {
... ...
} }
} }
void g() { void g() {
int status = doFoo(); int status = doFoo();
if (status == OK) { if (status == OK) {
... ...
} }
} }
void err() { void err() {
doFoo(); //doFoo is called but its return value is not checked, and doFoo(); //doFoo is called but its return value is not checked, and
//the value is checked in other locations //the value is checked in other locations
... ...
} }

View File

@@ -1,10 +1,10 @@
#define RECORD_SIZE 30 //incorrect or outdated size for record #define RECORD_SIZE 30 //incorrect or outdated size for record
typedef struct { typedef struct {
char name[30]; char name[30];
int status; int status;
} Record; } Record;
void f() { void f() {
Record* p = malloc(RECORD_SIZE); //not of sufficient size to hold a Record Record* p = malloc(RECORD_SIZE); //not of sufficient size to hold a Record
... ...
} }

View File

@@ -1,4 +1,4 @@
{ {
int foo = 1; int foo = 1;
... //foo is unused ... //foo is unused
} }

View File

@@ -1,9 +1,9 @@
int f() { int f() {
char* buf = new char[SIZE]; char* buf = new char[SIZE];
.... ....
if (error) { if (error) {
free(buf); //error handling has freed the buffer free(buf); //error handling has freed the buffer
} }
... ...
log_contents(buf); //but it is still used here for logging log_contents(buf); //but it is still used here for logging
} }

View File

@@ -1,4 +1,4 @@
int isOdd(int n) { int isOdd(int n) {
//TODO: Works only for positive n. Need to check if negative n is valid input //TODO: Works only for positive n. Need to check if negative n is valid input
return (n % 2) == 1; return (n % 2) == 1;
} }

View File

@@ -1,8 +1,8 @@
// header_file.h // header_file.h
#ifndef HEADER_FILE_H #ifndef HEADER_FILE_H
#define HEADER_FILE_H #define HEADER_FILE_H
// ... // ...
#endif // HEADER_FILE_H #endif // HEADER_FILE_H

View File

@@ -1,8 +1,8 @@
// another_header_file.h // another_header_file.h
#ifndef HEADER_FILE_H // should be ANOTHER_HEADER_FILE_H #ifndef HEADER_FILE_H // should be ANOTHER_HEADER_FILE_H
#define HEADER_FILE_H // should be ANOTHER_HEADER_FILE_H #define HEADER_FILE_H // should be ANOTHER_HEADER_FILE_H
// ... // ...
#endif // HEADER_FILE_H #endif // HEADER_FILE_H

View File

@@ -1,6 +1,6 @@
void h() { void h() {
int a, b, c; int a, b, c;
a < b != c; //parenthesize to explicitly define order of operators a < b != c; //parenthesize to explicitly define order of operators
(a < b) < c; //correct: parenthesized to specify order (a < b) < c; //correct: parenthesized to specify order
} }

View File

@@ -21,17 +21,19 @@ import semmle.code.cpp.controlflow.SSA
/** /**
* Holds if `e` is either: * Holds if `e` is either:
* - a constant * - a constant
* - a char-typed expression, meaning it's a small number
* - an array access to an array of constants * - an array access to an array of constants
* - flows from one of the above * - flows from one of the above
* In these cases the value of `e` is likely to be small and * In these cases the value of `e` is likely to be small and
* controlled, so we consider it less likely to cause an overflow. * controlled, so we consider it less likely to cause an overflow.
*/ */
predicate effectivelyConstant(Expr e) { predicate likelySmall(Expr e) {
e.isConstant() or e.isConstant() or
e.getType().getSize() <= 1 or
e.(ArrayExpr).getArrayBase().getType().(ArrayType).getBaseType().isConst() or e.(ArrayExpr).getArrayBase().getType().(ArrayType).getBaseType().isConst() or
exists(SsaDefinition def, Variable v | exists(SsaDefinition def, Variable v |
def.getAUse(v) = e and def.getAUse(v) = e and
effectivelyConstant(def.getDefiningValue(v)) likelySmall(def.getDefiningValue(v))
) )
} }
@@ -56,7 +58,7 @@ int getEffectiveMulOperands(MulExpr me) {
result = count(Expr op | result = count(Expr op |
op = getMulOperand*(me) and op = getMulOperand*(me) and
not op instanceof MulExpr and not op instanceof MulExpr and
not effectivelyConstant(op) not likelySmall(op)
) )
} }

View File

@@ -1,13 +1,13 @@
//Function foo's array parameter has a specified size //Function foo's array parameter has a specified size
void foo(int a[10]) { void foo(int a[10]) {
int i = 0; int i = 0;
for (i = 0; i <10; i++) { for (i = 0; i <10; i++) {
a[i] = i * 2; a[i] = i * 2;
} }
} }
... ...
int my_arr[5]; int my_arr[5];
foo(my_arr); //my_arr is smaller than foo's array parameter, and will cause access to memory outside its bounds foo(my_arr); //my_arr is smaller than foo's array parameter, and will cause access to memory outside its bounds

View File

@@ -1,4 +1,4 @@
//sz is a signed integer, but malloc expects one that is unsigned. //sz is a signed integer, but malloc expects one that is unsigned.
//Negative values will be interpreted as a large number, which may //Negative values will be interpreted as a large number, which may
//lead to unexpected behavior //lead to unexpected behavior
char *buf = malloc(sz); char *buf = malloc(sz);

View File

@@ -1,5 +1,5 @@
void f(char *p) { void f(char *p) {
int my_ptr = p; //Wrong: pointer assigned to int, would be incorrect if sizeof(char*) int my_ptr = p; //Wrong: pointer assigned to int, would be incorrect if sizeof(char*)
//is larger than sizeof(int) //is larger than sizeof(int)
//... //...
} }

View File

@@ -1,30 +1,30 @@
struct property { struct property {
char *name; char *name;
int value; int value;
}; };
struct property * get_property(char *key); struct property * get_property(char *key);
struct property * get_property_default(char *key, int default_value); struct property * get_property_default(char *key, int default_value);
void check_properties() { void check_properties() {
// this call will get flagged since most // this call will get flagged since most
// calls to get_property handle NULL // calls to get_property handle NULL
struct property *p1 = get_property("time"); struct property *p1 = get_property("time");
if(p1->value > 600) { if(p1->value > 600) {
... ...
} }
// this call will not get flagged since // this call will not get flagged since
// the result of the call is checked for NULL // the result of the call is checked for NULL
struct property *p2 = get_property("time"); struct property *p2 = get_property("time");
if(p2 != NULL && p2->value > 600) { if(p2 != NULL && p2->value > 600) {
... ...
} }
// this call will not get flagged since calls // this call will not get flagged since calls
// to get_property_default rarely handle NULL // to get_property_default rarely handle NULL
struct property *p3 = get_property_default("time", 50); struct property *p3 = get_property_default("time", 50);
if(p3->value > 60) { if(p3->value > 60) {
... ...
} }
} }

View File

@@ -1,13 +1,13 @@
if (!flags & SOME_BIT) { //wrong: '!' has higher precedence than '&', so this if (!flags & SOME_BIT) { //wrong: '!' has higher precedence than '&', so this
// is bracketed as '(!flags) & SOME_BIT', and does not // is bracketed as '(!flags) & SOME_BIT', and does not
// check whether a particular bit is set. // check whether a particular bit is set.
// ... // ...
} }
if ((p != NULL) & p->f()) { //wrong: The use of '&' rather than '&&' will still if ((p != NULL) & p->f()) { //wrong: The use of '&' rather than '&&' will still
// de-reference the pointer even if it is NULL. // de-reference the pointer even if it is NULL.
// ... // ...
} }
int bits = (s > 8) & 0xff; //wrong: Invalid attempt to get the 8 most significant int bits = (s > 8) & 0xff; //wrong: Invalid attempt to get the 8 most significant
// bits of a short. // bits of a short.

View File

@@ -1,11 +1,11 @@
if (0 || condition) { //wrong: can be converted to just 'condition' if (0 || condition) { //wrong: can be converted to just 'condition'
//... //...
} }
if (0 && condition) { //wrong: always evaluates to false, if statement can be removed if (0 && condition) { //wrong: always evaluates to false, if statement can be removed
// ... // ...
} }
if ('A' == 65 && condition) { // wrong: can be converted to just 'condition' if ('A' == 65 && condition) { // wrong: can be converted to just 'condition'
// ... // ...
} }

View File

@@ -1,30 +1,30 @@
typedef enum { typedef enum {
RED, RED,
ORANGE, ORANGE,
YELLOW, YELLOW,
GREEN, GREEN,
BLUE, BLUE,
INDIGO, INDIGO,
VIOLET VIOLET
} colors; } colors;
int f(colors c) { int f(colors c) {
switch (c) { switch (c) {
case RED: case RED:
//... //...
case GREEN: case GREEN:
//... //...
case BLUE: case BLUE:
//... //...
//wrong: does not use all enum values, and has no default //wrong: does not use all enum values, and has no default
} }
switch(c) { switch(c) {
case RED: case RED:
//... //...
case GREEN: case GREEN:
//... //...
default: default:
//correct: does not use all enum values, but has a default //correct: does not use all enum values, but has a default
} }
} }

View File

@@ -1,12 +1,12 @@
void f(char* s, float f) { void f(char* s, float f) {
char buf[30]; char buf[30];
//wrong: gets has no limit to the length of data it puts in the buffer //wrong: gets has no limit to the length of data it puts in the buffer
gets(buf); gets(buf);
//wrong: sprintf does not limit the length of the string put into buf //wrong: sprintf does not limit the length of the string put into buf
sprintf(buf, "This is a string: %s", s); sprintf(buf, "This is a string: %s", s);
//wrong: %f can expand to a very long string in extreme cases, easily overrunning this buffer //wrong: %f can expand to a very long string in extreme cases, easily overrunning this buffer
sprintf(buf, "This is a float: %f", f); sprintf(buf, "This is a float: %f", f);
} }

View File

@@ -1,4 +1,4 @@
strncat(dest, src, strlen(dest)); //wrong: should use remaining size of dest strncat(dest, src, strlen(dest)); //wrong: should use remaining size of dest
strncat(dest, src, sizeof(dest)); //wrong: should use remaining size of dest. strncat(dest, src, sizeof(dest)); //wrong: should use remaining size of dest.
//Also fails if dest is a pointer and not an array. //Also fails if dest is a pointer and not an array.

View File

@@ -1,4 +1,4 @@
void f(char s[]) { void f(char s[]) {
int size = sizeof(s); //wrong: s is now a char*, not an array. int size = sizeof(s); //wrong: s is now a char*, not an array.
//sizeof(s) will evaluate to sizeof(char *) //sizeof(s) will evaluate to sizeof(char *)
} }

View File

@@ -1,16 +1,16 @@
int x1 = 0; int x1 = 0;
for (x1 = 0; x1 < 100; x1++) { for (x1 = 0; x1 < 100; x1++) {
int x2 = 0; int x2 = 0;
for (x1 = 0; x1 < 300; x1++) { for (x1 = 0; x1 < 300; x1++) {
// this is most likely a typo // this is most likely a typo
// the outer loop will exit immediately // the outer loop will exit immediately
} }
} }
for (x1 = 0; x1 < 100; x1++) { for (x1 = 0; x1 < 100; x1++) {
if(x1 == 10 && condition) { if(x1 == 10 && condition) {
for (; x1 < 75; x1++) { for (; x1 < 75; x1++) {
// this should be written as a while loop // this should be written as a while loop
} }
} }
} }

View File

@@ -1,31 +1,31 @@
class Base { class Base {
public: public:
Resource *p; Resource *p;
Base() { Base() {
p = createResource(); p = createResource();
} }
//... //...
~Base() { ~Base() {
//wrong: this destructor is non-virtual, but Base has a derived class //wrong: this destructor is non-virtual, but Base has a derived class
// with a non-virtual destructor // with a non-virtual destructor
freeResource(p); freeResource(p);
} }
}; };
class Derived: public Base { class Derived: public Base {
public: public:
Resource *dp; Resource *dp;
Derived() { Derived() {
dp = createResource2(); dp = createResource2();
} }
~Derived() { ~Derived() {
freeResource2(dp); freeResource2(dp);
} }
}; };
int f() { int f() {
Base *b = new Derived(); //creates resources for both Base::p and Derived::dp Base *b = new Derived(); //creates resources for both Base::p and Derived::dp
//... //...
delete b; //will only call Base::~Base(), leaking the resource dp. delete b; //will only call Base::~Base(), leaking the resource dp.
// Change both destructors to virtual to ensure they are both called. // Change both destructors to virtual to ensure they are both called.
} }

View File

@@ -1,19 +1,19 @@
class C { class C {
public: public:
//... //...
~C(){ ~C(){
if (error) { if (error) {
throw "Exception in destructor"; //wrong: exception thrown in destructor throw "Exception in destructor"; //wrong: exception thrown in destructor
} }
} }
}; };
void f() { void f() {
C* c = new C(); C* c = new C();
try { try {
doOperation(c); doOperation(c);
delete c; delete c;
} catch ( char * do_operation_exception) { } catch ( char * do_operation_exception) {
delete c; //would immediately terminate program if C::~C throws an exception delete c; //would immediately terminate program if C::~C throws an exception
} }
} }

View File

@@ -1,14 +1,14 @@
int i = 0; int i = 0;
for (i = 0; i < NUM_RECORDS; i++) { for (i = 0; i < NUM_RECORDS; i++) {
int j = 0; int j = 0;
//This loop should have a more descriptive iteration variable //This loop should have a more descriptive iteration variable
for (j = 0; j < NUM_FIELDS; j++) { for (j = 0; j < NUM_FIELDS; j++) {
process(record[i]->field[j]); process(record[i]->field[j]);
} }
int field_idx = 0; int field_idx = 0;
//Better: the inner loop has a descriptive name //Better: the inner loop has a descriptive name
for (field_idx = 0; field_idx < NUM_FIELDS; field_idx++) { for (field_idx = 0; field_idx < NUM_FIELDS; field_idx++) {
save(record[i]->field[field_idx]); save(record[i]->field[field_idx]);
} }
} }

View File

@@ -1,28 +1,28 @@
void main(int argc, char **argv) { void main(int argc, char **argv) {
uint32_t big_num = INT32_MAX; uint32_t big_num = INT32_MAX;
char buf[big_num]; char buf[big_num];
int16_t bytes_received = 0; int16_t bytes_received = 0;
int max_get = INT16_MAX + 1; int max_get = INT16_MAX + 1;
// BAD: 'bytes_received' is compared with a value of a wider type. // BAD: 'bytes_received' is compared with a value of a wider type.
// 'bytes_received' overflows before reaching 'max_get', // 'bytes_received' overflows before reaching 'max_get',
// causing an infinite loop // causing an infinite loop
while (bytes_received < max_get) while (bytes_received < max_get)
bytes_received += get_from_input(buf, bytes_received); bytes_received += get_from_input(buf, bytes_received);
} }
uint32_t bytes_received = 0; uint32_t bytes_received = 0;
// GOOD: 'bytes_received2' has a type at least as wide as 'max_get' // GOOD: 'bytes_received2' has a type at least as wide as 'max_get'
while (bytes_received < max_get) { while (bytes_received < max_get) {
bytes_received += get_from_input(buf, bytes_received); bytes_received += get_from_input(buf, bytes_received);
} }
} }
int getFromInput(char *buf, short pos) { int getFromInput(char *buf, short pos) {
// write to buf // write to buf
// ... // ...
return 1; return 1;
} }

View File

@@ -0,0 +1,7 @@
LPMALLOC pMalloc;
HRESULT hr = CoGetMalloc(1, &pMalloc);
if (!hr)
{
// code ...
}

View File

@@ -0,0 +1,26 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>This query indicates that an <code>HRESULT</code> is being cast to a boolean type or vice versa.</p>
<p>The typical success value (<code>S_OK</code>) of an <code>HRESULT</code> equals 0. However, 0 indicates failure for a boolean type.</p>
<p>Casting an <code>HRESULT</code> to a boolean type and then using it in a test expression will yield an incorrect result.</p>
</overview>
<recommendation>
<p>To check if a call that returns an HRESULT succeeded use the <code>FAILED</code> macro.</p>
</recommendation>
<example>
<p>In the following example, <code>HRESULT</code> is used in a test expression incorrectly as it may yield an incorrect result.</p>
<sample src="HResultBooleanConversion.cpp" />
<p>To fix this issue, use the <code>FAILED</code> macro in the test expression.</p>
</example>
<references>
</references>
</qhelp>

View File

@@ -0,0 +1,71 @@
/**
* @name Cast between semantically different integer types: HRESULT to/from a Boolean type
* @description Cast between semantically different integer types: HRESULT to/from a Boolean type.
* Boolean types indicate success by a non-zero value, whereas success (S_OK) in HRESULT is indicated by a value of 0.
* Casting an HRESULT to/from a Boolean type and then using it in a test expression will yield an incorrect result.
* @kind problem
* @id cpp/hresult-boolean-conversion
* @problem.severity error
* @precision high
* @tags security
* external/cwe/cwe-253
* external/microsoft/C6214
* external/microsoft/C6215
* external/microsoft/C6216
* external/microsoft/C6217
* external/microsoft/C6230
*/
import cpp
predicate isHresultBooleanConverted( Expr e1, Cast e2 )
{
exists ( Type t1, Type t2 |
t1 = e1.getType() and
t2 = e2.getType() and
((t1.hasName("bool") or t1.hasName("BOOL") or t1.hasName("_Bool")) and t2.hasName("HRESULT") or
(t2.hasName("bool") or t2.hasName("BOOL") or t2.hasName("_Bool")) and t1.hasName("HRESULT")
))
}
predicate isHresultBooleanConverted( Expr e1 )
{
exists( Cast e2 |
e2 = e1.getConversion() and
isHresultBooleanConverted(e1, e2)
)
}
from Expr e1, string msg
where exists
(
Cast e2 |
e2 = e1.getConversion() |
isHresultBooleanConverted( e1, e2 )
and if e2.isImplicit() then ( msg = "Implicit conversion from " + e1.getType().toString() + " to " + e2.getType().toString())
else ( msg = "Explicit conversion from " + e1.getType().toString() + " to " + e2.getType().toString())
)
or exists
(
ControlStructure ctls |
ctls.getControllingExpr() = e1
and e1.getType().(TypedefType).hasName("HRESULT")
and not isHresultBooleanConverted(e1)
and msg = "Direct usage of a type " + e1.getType().toString() + " as a conditional expression"
)
or
(
exists( BinaryLogicalOperation blop |
blop.getAnOperand() = e1 |
e1.getType().(TypedefType).hasName("HRESULT")
and msg = "Usage of a type " + e1.getType().toString() + " as an argument of a binary logical operation"
)
or exists
(
UnaryLogicalOperation ulop |
ulop.getAnOperand() = e1 |
e1.getType().(TypedefType).hasName("HRESULT")
and msg = "Usage of a type " + e1.getType().toString() + " as an argument of a unary logical operation"
)
and not isHresultBooleanConverted(e1)
)
select e1, msg

View File

@@ -10,33 +10,69 @@
* external/cwe/cwe-404 * external/cwe/cwe-404
*/ */
import cpp import cpp
import Critical.NewDelete
// List pairs of functions that do resource acquisition/release /**
// Extend this to add custom function pairs. As written the query * An expression that acquires a resource, and the kind of resource that is acquired. The
// will only apply if the resource is the *return value* of the * kind of a resource indicates which acquisition/release expressions can be paired.
// first call and a *parameter* to the second. Other cases should */
// be handled differently. predicate acquireExpr(Expr acquire, string kind) {
predicate resourceManagementPair(string acquire, string release) { exists(FunctionCall fc, Function f, string name |
fc = acquire and
(acquire = "fopen" and release = "fclose") f = fc.getTarget() and
or name = f.getName() and
(acquire = "open" and release = "close") (
or (
(acquire = "socket" and release = "close") name = "fopen" and
kind = "file"
) or (
name = "open" and
kind = "file descriptor"
) or (
name = "socket" and
kind = "file descriptor"
)
)
) or (
allocExpr(acquire, kind)
)
} }
// List functions that return malloc-allocated memory. Customize /**
// to list your own functions there * An expression that releases a resource, and the kind of resource that is released. The
predicate mallocFunction(Function malloc) { * kind of a resource indicates which acquisition/release expressions can be paired.
malloc.hasName("malloc") or malloc.hasName("calloc") or // Not realloc: doesn't acquire it, really */
malloc.hasName("strdup") predicate releaseExpr(Expr release, Expr resource, string kind) {
} exists(FunctionCall fc, Function f, string name |
fc = release and
private predicate isRelease(string release) { f = fc.getTarget() and
resourceManagementPair(_, release) or name = f.getName() and
release = "free" or (
release = "delete" (
name = "fclose" and
resource = fc.getArgument(0) and
kind = "file"
) or (
name = "close" and
resource = fc.getArgument(0) and
kind = "file descriptor"
)
)
) or exists(string releaseKind |
freeExpr(release, resource, releaseKind) and
(
(
kind = "malloc" and
releaseKind = "free"
) or (
kind = "new" and
releaseKind = "delete"
) or (
kind = "new[]" and
releaseKind = "delete[]"
)
)
)
} }
/** /**
@@ -52,35 +88,23 @@ Expr exprOrDereference(Expr e) {
* Holds if the expression `e` releases expression `released`, whether directly * Holds if the expression `e` releases expression `released`, whether directly
* or via one or more function call(s). * or via one or more function call(s).
*/ */
private predicate exprReleases(Expr e, Expr released, string releaseType) { private predicate exprReleases(Expr e, Expr released, string kind) {
( (
// `e` is a call to a release function and `released` is any argument // `e` is a call to a release function and `released` is the released argument
e.(FunctionCall).getTarget().getName() = releaseType and releaseExpr(e, released, kind)
isRelease(releaseType) and
e.(FunctionCall).getAnArgument() = released
) or (
// `e` is a call to `delete` and `released` is the target
e.(DeleteExpr).getExpr() = released and
releaseType = "delete"
) or (
// `e` is a call to `delete[]` and `released` is the target
e.(DeleteArrayExpr).getExpr() = released and
releaseType = "delete"
) or exists(Function f, int arg | ) or exists(Function f, int arg |
// `e` is a call to a function that releases one of it's parameters, // `e` is a call to a function that releases one of it's parameters,
// and `released` is the corresponding argument // and `released` is the corresponding argument
e.(FunctionCall).getTarget() = f and e.(FunctionCall).getTarget() = f and
e.(FunctionCall).getArgument(arg) = released and e.(FunctionCall).getArgument(arg) = released and
exprReleases(_, exprOrDereference(f.getParameter(arg).getAnAccess()), releaseType) exprReleases(_, exprOrDereference(f.getParameter(arg).getAnAccess()), kind)
) or exists(Function f, Expr innerThis | ) or exists(Function f, ThisExpr innerThis |
// `e` is a call to a method that releases `this`, and `released` // `e` is a call to a method that releases `this`, and `released`
// is the object that is called // is the object that is called
e.(FunctionCall).getTarget() = f and e.(FunctionCall).getTarget() = f and
e.(FunctionCall).getQualifier() = exprOrDereference(released) and e.(FunctionCall).getQualifier() = exprOrDereference(released) and
innerThis.getEnclosingFunction() = f and innerThis.getEnclosingFunction() = f and
exprReleases(_, innerThis, releaseType) and exprReleases(_, innerThis, kind)
innerThis instanceof ThisExpr and
releaseType = "delete"
) )
} }
@@ -109,28 +133,17 @@ class Resource extends MemberVariable {
) )
} }
predicate acquisitionWithRequiredRelease(Expr acquire, string releaseName) { predicate acquisitionWithRequiredRelease(Assignment acquireAssign, string kind) {
acquire.(Assignment).getLValue() = this.getAnAccess() and // acquireAssign is an assignment to this resource
acquireAssign.(Assignment).getLValue() = this.getAnAccess() and
// Should be in this class, but *any* member method will do // Should be in this class, but *any* member method will do
this.inSameClass(acquire) and this.inSameClass(acquireAssign) and
// Check that it is an acquisition function and return the corresponding free // Check that it is an acquisition function and return the corresponding free
( acquireExpr(acquireAssign.getRValue(), kind)
exists(Function f | f = acquire.(Assignment).getRValue().(FunctionCall).getTarget() and
(resourceManagementPair(f.getName(), releaseName) or (mallocFunction(f) and (releaseName = "free" or releaseName = "delete")))
)
or
(acquire = this.getANew() and releaseName = "delete")
)
} }
private Assignment getANew() { Expr getAReleaseExpr(string kind) {
result.getLValue() = this.getAnAccess() and exprReleases(result, this.getAnAccess(), kind)
(result.getRValue() instanceof NewExpr or result.getRValue() instanceof NewArrayExpr) and
this.inSameClass(result)
}
Expr getAReleaseExpr(string releaseName) {
exprReleases(result, this.getAnAccess(), releaseName)
} }
} }

View File

@@ -1,20 +1,20 @@
enum Shape_color { red, green, blue }; enum Shape_color { red, green, blue };
class Shape class Shape
{ {
public: public:
virtual void draw (Shape_color color = green) const; virtual void draw (Shape_color color = green) const;
... ...
} }
class Circle : public Shape class Circle : public Shape
{ {
public: public:
virtual void draw (Shape_color color = red) const; virtual void draw (Shape_color color = red) const;
... ...
} }
void fun() void fun()
{ {
Shape* sp; Shape* sp;
sp = new Circle; sp = new Circle;
sp->draw (); // Invokes Circle::draw(green) even though the default sp->draw (); // Invokes Circle::draw(green) even though the default
} // parameter for Circle is red. } // parameter for Circle is red.

View File

@@ -1,16 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.2"?> <?eclipse version="3.2"?>
<plugin> <plugin>
<extension point="com.semmle.plugin.qdt.ui.resources"> <extension point="com.semmle.plugin.qdt.ui.resources">
<name value="semmlecode-cpp-queries"/> <name value="semmlecode-cpp-queries"/>
</extension> </extension>
<extension point="com.semmle.plugin.qdt.ui.resources"> <extension point="com.semmle.plugin.qdt.ui.resources">
<name value="com.semmle.code.cpp.library"/> <name value="com.semmle.code.cpp.library"/>
</extension> </extension>
<extension point="com.semmle.plugin.qdt.ui.resources"> <extension point="com.semmle.plugin.qdt.ui.resources">
<name value="com.semmle.code.cpp.dbscheme"/> <name value="com.semmle.code.cpp.dbscheme"/>
<path value="/semmlecode.cpp.dbscheme"/> <path value="/semmlecode.cpp.dbscheme"/>
</extension> </extension>
</plugin> </plugin>

View File

@@ -68,10 +68,9 @@ class Parameter extends LocalScopeVariable, @parameter {
*/ */
private VariableDeclarationEntry getAnEffectiveDeclarationEntry() { private VariableDeclarationEntry getAnEffectiveDeclarationEntry() {
if getFunction().isConstructedFrom(_) if getFunction().isConstructedFrom(_)
then exists (Parameter prototype then exists (Function prototypeInstantiation
| prototype = result.getVariable() and | prototypeInstantiation.getParameter(getIndex()) = result.getVariable() and
prototype.getIndex() = getIndex() and getFunction().isConstructedFrom(prototypeInstantiation))
getFunction().isConstructedFrom(prototype.getFunction()))
else result = getADeclarationEntry() else result = getADeclarationEntry()
} }

View File

@@ -1,23 +1,31 @@
import semmle.code.cpp.Type import semmle.code.cpp.Type
/** Holds if `d` is a complete class named `name`. */ pragma[noinline]
private string getTopLevelClassName(@usertype c) {
isClass(c) and
usertypes(c, result, _) and
not namespacembrs(_, c) and // not in a namespace
not member(_, _, c) and // not in some structure
not class_instantiation(c, _) // not a template instantiation
}
/** Holds if `d` is a unique complete class named `name`. */
pragma[noinline] pragma[noinline]
private predicate existsCompleteWithName(string name, @usertype d) { private predicate existsCompleteWithName(string name, @usertype d) {
isClass(d) and
is_complete(d) and is_complete(d) and
usertypes(d, name, _) name = getTopLevelClassName(d) and
strictcount(@usertype other | is_complete(other) and getTopLevelClassName(other) = name) = 1
} }
/** Holds if `c` is an incomplete class named `name`. */ /** Holds if `c` is an incomplete class named `name`. */
pragma[noinline] pragma[noinline]
private predicate existsIncompleteWithName(string name, @usertype c) { private predicate existsIncompleteWithName(string name, @usertype c) {
isClass(c) and
not is_complete(c) and not is_complete(c) and
usertypes(c, name, _) name = getTopLevelClassName(c)
} }
/** /**
* Holds if `c` is an incomplete class, and there exists a complete class `d` * Holds if `c` is an incomplete class, and there exists a unique complete class `d`
* with the same name. * with the same name.
*/ */
private predicate hasCompleteTwin(@usertype c, @usertype d) { private predicate hasCompleteTwin(@usertype c, @usertype d) {
@@ -30,10 +38,8 @@ private predicate hasCompleteTwin(@usertype c, @usertype d) {
import Cached import Cached
cached private module Cached { cached private module Cached {
/** /**
* If `c` is incomplete, and there exists a complete class with the same name, * If `c` is incomplete, and there exists a unique complete class with the same name,
* then the result is that complete class. Otherwise, the result is `c`. If * then the result is that complete class. Otherwise, the result is `c`.
* multiple complete classes have the same name, this predicate may have
* multiple results.
*/ */
cached @usertype resolveClass(@usertype c) { cached @usertype resolveClass(@usertype c) {
hasCompleteTwin(c, result) hasCompleteTwin(c, result)

View File

@@ -270,7 +270,7 @@ newtype TTranslatedElement =
not ignoreExpr(initList) and not ignoreExpr(initList) and
isFirstValueInitializedElementInRange(initList, elementIndex) and isFirstValueInitializedElementInRange(initList, elementIndex) and
elementCount = elementCount =
getNextExplicitlyInitializedElementAfter(initList, elementIndex) - getEndOfValueInitializedRange(initList, elementIndex) -
elementIndex elementIndex
} or } or
// The initialization of a base class from within a constructor. // The initialization of a base class from within a constructor.
@@ -322,23 +322,30 @@ newtype TTranslatedElement =
/** /**
* Gets the index of the first explicitly initialized element in `initList` * Gets the index of the first explicitly initialized element in `initList`
* whose index is greater than `afterElementIndex`. If there are no remaining * whose index is greater than `afterElementIndex`, where `afterElementIndex`
* explicitly initialized elements in `initList`, the result is the total number * is a first value-initialized element in a value-initialized range in
* of elements in the array being initialized. * `initList`. If there are no remaining explicitly initialized elements in
* `initList`, the result is the total number of elements in the array being
* initialized.
*/ */
private int getNextExplicitlyInitializedElementAfter( private int getEndOfValueInitializedRange(ArrayAggregateLiteral initList, int afterElementIndex) {
ArrayAggregateLiteral initList, int afterElementIndex) { result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)
if exists(int x | or
x > afterElementIndex and isFirstValueInitializedElementInRange(initList, afterElementIndex) and
exists(initList.getElementExpr(x))) not exists(getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)) and
then ( result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize()
if exists(initList.getElementExpr(afterElementIndex + 1)) }
then result = afterElementIndex + 1
else result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex+1)) /**
else * Gets the index of the first explicitly initialized element in `initList`
result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize() and * whose index is greater than `afterElementIndex`, where `afterElementIndex`
// required for binding * is a first value-initialized element in a value-initialized range in
initList.isInitialized(afterElementIndex) * `initList`.
*/
private int getNextExplicitlyInitializedElementAfter(
ArrayAggregateLiteral initList, int afterElementIndex) {
isFirstValueInitializedElementInRange(initList, afterElementIndex) and
result = min(int i | exists(initList.getElementExpr(i)) and i > afterElementIndex)
} }
/** /**

View File

@@ -1,137 +1,137 @@
import sys import sys
import os.path import os.path
import glob import glob
import re import re
import json import json
BEGIN_TEMPLATE = re.compile(r"^/\*template\s*$") BEGIN_TEMPLATE = re.compile(r"^/\*template\s*$")
END_TEMPLATE = re.compile(r"^\*/\s*$") END_TEMPLATE = re.compile(r"^\*/\s*$")
def expand_template_params(args, param_arg_map): def expand_template_params(args, param_arg_map):
'''Given a list of template arguments that may reference template parameters '''Given a list of template arguments that may reference template parameters
of the current template, return a new list of template arguments with each of the current template, return a new list of template arguments with each
parameter use replaced with the appropriate fully-qualified argument for parameter use replaced with the appropriate fully-qualified argument for
that parameter.''' that parameter.'''
result = [] result = []
for arg in args: for arg in args:
if arg in param_arg_map: if arg in param_arg_map:
result.append(param_arg_map[arg]) result.append(param_arg_map[arg])
else: else:
result.append(arg) result.append(arg)
return result return result
def find_instantiation(module, args, templates): def find_instantiation(module, args, templates):
'''Given a template module and a set of template arguments, find the module '''Given a template module and a set of template arguments, find the module
name of the instantiation of that module with those arguments.''' name of the instantiation of that module with those arguments.'''
template = templates[module] template = templates[module]
for instantiation in template["template_def"]["instantiations"]: for instantiation in template["template_def"]["instantiations"]:
if instantiation["args"] == args: if instantiation["args"] == args:
return instantiation["name"] return instantiation["name"]
return None return None
def instantiate_template(template, instantiation, root, templates): def instantiate_template(template, instantiation, root, templates):
'''Create a single instantiation of a template.''' '''Create a single instantiation of a template.'''
template_def = template["template_def"] template_def = template["template_def"]
output_components = instantiation["name"].split(".") output_components = instantiation["name"].split(".")
output_path = root output_path = root
for component in output_components: for component in output_components:
output_path = os.path.join(output_path, component) output_path = os.path.join(output_path, component)
output_path = output_path + ".qll" output_path = output_path + ".qll"
with open(output_path, "w") as output: with open(output_path, "w") as output:
output.write( output.write(
""" """
/* /*
* THIS FILE IS AUTOMATICALLY GENERATED FROM '%s'. * THIS FILE IS AUTOMATICALLY GENERATED FROM '%s'.
* DO NOT EDIT MANUALLY. * DO NOT EDIT MANUALLY.
*/ */
""" % (template["name"].replace(".", "/") + ".qllt") """ % (template["name"].replace(".", "/") + ".qllt")
) )
param_arg_map = {} param_arg_map = {}
for param_index in range(len(template_def["params"])): for param_index in range(len(template_def["params"])):
param = template_def["params"][param_index] param = template_def["params"][param_index]
arg = instantiation["args"][param_index] arg = instantiation["args"][param_index]
output.write("private import %s as %s // Template parameter\n" % (arg, param)) output.write("private import %s as %s // Template parameter\n" % (arg, param))
param_arg_map[param] = arg param_arg_map[param] = arg
for import_record in template_def["imports"]: for import_record in template_def["imports"]:
if "access" in import_record: if "access" in import_record:
output.write(import_record["access"] + " ") output.write(import_record["access"] + " ")
imported_module = find_instantiation(import_record["module"], imported_module = find_instantiation(import_record["module"],
expand_template_params(import_record["args"], param_arg_map), templates) expand_template_params(import_record["args"], param_arg_map), templates)
output.write("import %s // %s<%s>\n" % output.write("import %s // %s<%s>\n" %
( (
imported_module, imported_module,
import_record["module"], import_record["module"],
", ".join(import_record["args"]) ", ".join(import_record["args"])
) )
) )
output.writelines(template_def["body_lines"]) output.writelines(template_def["body_lines"])
def generate_instantiations(template, root, templates): def generate_instantiations(template, root, templates):
'''Create a .qll source file for each instantiation of the specified template.''' '''Create a .qll source file for each instantiation of the specified template.'''
template_def = template["template_def"] template_def = template["template_def"]
if "instantiations" in template_def: if "instantiations" in template_def:
for instantiation in template_def["instantiations"]: for instantiation in template_def["instantiations"]:
instantiate_template(template, instantiation, root, templates) instantiate_template(template, instantiation, root, templates)
def read_template(template_path, module_name): def read_template(template_path, module_name):
'''Read a .qllt template file from template_path, using module_name as the '''Read a .qllt template file from template_path, using module_name as the
fully qualified name of the module.''' fully qualified name of the module.'''
with open(template_path) as input: with open(template_path) as input:
in_template = False in_template = False
template_text = "" template_text = ""
template_def = None template_def = None
body_lines = [] body_lines = []
for line in iter(input): for line in iter(input):
if in_template: if in_template:
if END_TEMPLATE.match(line): if END_TEMPLATE.match(line):
template_def = json.loads(template_text) template_def = json.loads(template_text)
in_template = False in_template = False
else: else:
template_text += line template_text += line
else: else:
if BEGIN_TEMPLATE.match(line) and not template_def: if BEGIN_TEMPLATE.match(line) and not template_def:
in_template = True in_template = True
else: else:
body_lines.append(line) body_lines.append(line)
if template_def: if template_def:
template_def["body_lines"] = body_lines template_def["body_lines"] = body_lines
result = { "name": module_name } result = { "name": module_name }
if template_def: if template_def:
result["template_def"] = template_def result["template_def"] = template_def
return result return result
def module_name_from_path_impl(path): def module_name_from_path_impl(path):
(head, tail) = os.path.split(path) (head, tail) = os.path.split(path)
if head == "": if head == "":
return tail return tail
else: else:
return module_name_from_path(head) + "." + tail return module_name_from_path(head) + "." + tail
def module_name_from_path(path): def module_name_from_path(path):
'''Compute the fully qualified name of a module from the path of its .qll[t] '''Compute the fully qualified name of a module from the path of its .qll[t]
file. The path should be relative to the library root.''' file. The path should be relative to the library root.'''
(module_root, ext) = os.path.splitext(path) (module_root, ext) = os.path.splitext(path)
return module_name_from_path_impl(module_root) return module_name_from_path_impl(module_root)
def main(): def main():
templates = {} templates = {}
root = sys.argv[1] root = sys.argv[1]
for template_path in glob.glob(os.path.join(root, "**\\*.qllt"), recursive = True): for template_path in glob.glob(os.path.join(root, "**\\*.qllt"), recursive = True):
print(template_path) print(template_path)
module_name = module_name_from_path(os.path.relpath(template_path, root)) module_name = module_name_from_path(os.path.relpath(template_path, root))
print(module_name) print(module_name)
template = read_template(template_path, module_name) template = read_template(template_path, module_name)
templates[template["name"]] = template templates[template["name"]] = template
for name, template in templates.items(): for name, template in templates.items():
if "template_def" in template: if "template_def" in template:
generate_instantiations(template, root, templates) generate_instantiations(template, root, templates)
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<projectDescription> <projectDescription>
<name>semmlecode-cpp-tests</name> <name>semmlecode-cpp-tests</name>
<comment></comment> <comment></comment>
<projects> <projects>
</projects> </projects>
<buildSpec> <buildSpec>
</buildSpec> </buildSpec>
<natures> <natures>
<nature>com.semmle.plugin.qdt.core.qlnature</nature> <nature>com.semmle.plugin.qdt.core.qlnature</nature>
</natures> </natures>
</projectDescription> </projectDescription>

View File

@@ -1,5 +1,5 @@
// common.h // common.h
#include "nameclash.h" #include "nameclash.h"
static int myArray[sizeof(MYTYPE)]; static int myArray[sizeof(MYTYPE)];

View File

@@ -1,3 +1,3 @@
// defines_issue.h // defines_issue.h
#include DEFINED_HEADER #include DEFINED_HEADER

View File

@@ -1,7 +1,7 @@
// semmle-extractor-options: -I${testdir}/subdir2 // semmle-extractor-options: -I${testdir}/subdir2
// main2.cpp // main2.cpp
#include "common.h" #include "common.h"
#define DEFINED_HEADER "define2.h" #define DEFINED_HEADER "define2.h"
#include "defines_issue.h" #include "defines_issue.h"

View File

@@ -1,3 +1,3 @@
// nameclash.h // nameclash.h
#include_next "nameclash.h" #include_next "nameclash.h"

View File

@@ -1,3 +1,3 @@
// subdir1/nameclash.h // subdir1/nameclash.h
typedef long long int MYTYPE; typedef long long int MYTYPE;

View File

@@ -1,3 +1,3 @@
// subdir2/nameclash.h // subdir2/nameclash.h
typedef char MYTYPE; typedef char MYTYPE;

View File

@@ -1,111 +1,111 @@
// semmle-extractor-options: -std=c++17 // semmle-extractor-options: -std=c++17
typedef unsigned long size_t; typedef unsigned long size_t;
namespace std { namespace std {
enum class align_val_t : size_t {}; enum class align_val_t : size_t {};
} }
void* operator new(size_t, float); void* operator new(size_t, float);
void* operator new[](size_t, float); void* operator new[](size_t, float);
void* operator new(size_t, std::align_val_t, float); void* operator new(size_t, std::align_val_t, float);
void* operator new[](size_t, std::align_val_t, float); void* operator new[](size_t, std::align_val_t, float);
void operator delete(void*, float); void operator delete(void*, float);
void operator delete[](void*, float); void operator delete[](void*, float);
void operator delete(void*, std::align_val_t, float); void operator delete(void*, std::align_val_t, float);
void operator delete[](void*, std::align_val_t, float); void operator delete[](void*, std::align_val_t, float);
struct String { struct String {
String(); String();
String(const String&); String(const String&);
String(String&&); String(String&&);
String(const char*); String(const char*);
~String(); ~String();
String& operator=(const String&); String& operator=(const String&);
String& operator=(String&&); String& operator=(String&&);
const char* c_str() const; const char* c_str() const;
private: private:
const char* p; const char* p;
}; };
struct SizedDealloc { struct SizedDealloc {
char a[32]; char a[32];
void* operator new(size_t); void* operator new(size_t);
void* operator new[](size_t); void* operator new[](size_t);
void operator delete(void*, size_t); void operator delete(void*, size_t);
void operator delete[](void*, size_t); void operator delete[](void*, size_t);
}; };
struct alignas(128) Overaligned { struct alignas(128) Overaligned {
char a[256]; char a[256];
}; };
struct PolymorphicBase { struct PolymorphicBase {
virtual ~PolymorphicBase(); virtual ~PolymorphicBase();
}; };
void OperatorNew() { void OperatorNew() {
new int; // No constructor new int; // No constructor
new(1.0f) int; // Placement new, no constructor new(1.0f) int; // Placement new, no constructor
new int(); // Zero-init new int(); // Zero-init
new String(); // Constructor new String(); // Constructor
new(1.0f) String("hello"); // Placement new, constructor with args new(1.0f) String("hello"); // Placement new, constructor with args
new Overaligned; // Aligned new new Overaligned; // Aligned new
new(1.0f) Overaligned(); // Placement aligned new new(1.0f) Overaligned(); // Placement aligned new
} }
void OperatorDelete() { void OperatorDelete() {
delete static_cast<int*>(nullptr); // No destructor delete static_cast<int*>(nullptr); // No destructor
delete static_cast<String*>(nullptr); // Non-virtual destructor, with size. delete static_cast<String*>(nullptr); // Non-virtual destructor, with size.
delete static_cast<SizedDealloc*>(nullptr); // No destructor, with size. delete static_cast<SizedDealloc*>(nullptr); // No destructor, with size.
delete static_cast<Overaligned*>(nullptr); // No destructor, with size and alignment. delete static_cast<Overaligned*>(nullptr); // No destructor, with size and alignment.
delete static_cast<PolymorphicBase*>(nullptr); // Virtual destructor delete static_cast<PolymorphicBase*>(nullptr); // Virtual destructor
delete static_cast<const String*>(nullptr); // Pointer to const delete static_cast<const String*>(nullptr); // Pointer to const
} }
void OperatorNewArray(int n) { void OperatorNewArray(int n) {
new int[n]; // No constructor new int[n]; // No constructor
new(1.0f) int[n]; // Placement new, no constructor new(1.0f) int[n]; // Placement new, no constructor
new String[n]; // Constructor new String[n]; // Constructor
new Overaligned[n]; // Aligned new new Overaligned[n]; // Aligned new
new String[10]; // Constant size new String[10]; // Constant size
} }
int* const GetPointer(); int* const GetPointer();
void OperatorDeleteArray() { void OperatorDeleteArray() {
delete[] static_cast<int*>(nullptr); // No destructor delete[] static_cast<int*>(nullptr); // No destructor
delete[] static_cast<String*>(nullptr); // Non-virtual destructor, with size. delete[] static_cast<String*>(nullptr); // Non-virtual destructor, with size.
delete[] static_cast<SizedDealloc*>(nullptr); // No destructor, with size. delete[] static_cast<SizedDealloc*>(nullptr); // No destructor, with size.
delete[] static_cast<Overaligned*>(nullptr); // No destructor, with size and alignment. delete[] static_cast<Overaligned*>(nullptr); // No destructor, with size and alignment.
delete[] static_cast<PolymorphicBase*>(nullptr); // Virtual destructor delete[] static_cast<PolymorphicBase*>(nullptr); // Virtual destructor
delete[] GetPointer(); delete[] GetPointer();
} }
struct FailedInit { struct FailedInit {
FailedInit(); FailedInit();
~FailedInit(); ~FailedInit();
void* operator new(size_t); // Non-placement void* operator new(size_t); // Non-placement
void* operator new[](size_t); // Non-placement void* operator new[](size_t); // Non-placement
void operator delete(void*, size_t); // Sized deallocation void operator delete(void*, size_t); // Sized deallocation
void operator delete[](void*, size_t); // Sized deallocation void operator delete[](void*, size_t); // Sized deallocation
}; };
struct alignas(128) FailedInitOveraligned { struct alignas(128) FailedInitOveraligned {
FailedInitOveraligned(); FailedInitOveraligned();
~FailedInitOveraligned(); ~FailedInitOveraligned();
void* operator new(size_t, std::align_val_t, float); // Aligned placement void* operator new(size_t, std::align_val_t, float); // Aligned placement
void* operator new[](size_t, std::align_val_t, float); // Aligned placement void* operator new[](size_t, std::align_val_t, float); // Aligned placement
void operator delete(void*, std::align_val_t, float); // Aligned placement void operator delete(void*, std::align_val_t, float); // Aligned placement
void operator delete[](void*, std::align_val_t, float); // Aligned placement void operator delete[](void*, std::align_val_t, float); // Aligned placement
}; };
void TestFailedInit(int n) { void TestFailedInit(int n) {
new FailedInit(); new FailedInit();
new FailedInit[n]; new FailedInit[n];
new(1.0f) FailedInitOveraligned(); new(1.0f) FailedInitOveraligned();
new(1.0f) FailedInitOveraligned[10]; new(1.0f) FailedInitOveraligned[10];
} }

View File

@@ -1,8 +1,8 @@
#include "calls1.h" #include "calls1.h"
void swap(int* p, int* q) void swap(int* p, int* q)
{ {
int t = *p; int t = *p;
*p = *q; *p = *q;
*q = t; *q = t;
} }

View File

@@ -1,2 +1,2 @@
extern void swap(int*, int*); extern void swap(int*, int*);

View File

@@ -1,20 +1,20 @@
#include "calls1.h" #include "calls1.h"
void g() { void g() {
int x = 2; int x = 2;
int y = 4; int y = 4;
swap(&x,&y); swap(&x,&y);
} }
void negate(int& c) { c = -c; } void negate(int& c) { c = -c; }
template<class Iter, class Fct> void compute(Iter b, Fct f) template<class Iter, class Fct> void compute(Iter b, Fct f)
{ {
f(b); f(b);
} }
void f(int aa) void f(int aa)
{ {
compute(aa, negate); compute(aa, negate);
} }

View File

@@ -1,41 +1,41 @@
class A { class A {
}; };
class B { class B {
}; };
class C: A, B { class C: A, B {
}; };
class D: C { class D: C {
class E; class E;
}; };
class D::E { class D::E {
class F; class F;
class G { class G {
public: public:
/* Non-trivial constructor and destructor */ /* Non-trivial constructor and destructor */
G() { 0; } G() { 0; }
~G() { 0; } ~G() { 0; }
}; };
}; };
class D::E::F: D::E::G { class D::E::F: D::E::G {
/* Should have generated constructor and destructor, because of D::E::G */ /* Should have generated constructor and destructor, because of D::E::G */
static int m() { static int m() {
D::E::F def; /* Should trigger creation of D::E::F's generated constructor and destructor. */ D::E::F def; /* Should trigger creation of D::E::F's generated constructor and destructor. */
} }
}; };
// semmle-extractor-options: --microsoft // semmle-extractor-options: --microsoft

View File

@@ -1,84 +1,84 @@
struct Base { struct Base {
int b1; int b1;
float b1f; float b1f;
}; };
struct SingleInheritance : Base { struct SingleInheritance : Base {
int si1; int si1;
float si1f; float si1f;
}; };
struct Base2 { struct Base2 {
int b2; int b2;
float b2f; float b2f;
}; };
struct MultipleInheritance : Base, Base2 { struct MultipleInheritance : Base, Base2 {
int mi1; int mi1;
float mi1f; float mi1f;
}; };
struct DeepInheritance : MultipleInheritance, SingleInheritance { struct DeepInheritance : MultipleInheritance, SingleInheritance {
int di1; int di1;
float di1f; float di1f;
}; };
struct VirtualInheritance1 : virtual Base { struct VirtualInheritance1 : virtual Base {
int vi1; int vi1;
float vi1f; float vi1f;
}; };
struct VirtualInheritance2 : VirtualInheritance1, virtual Base, virtual Base2 { struct VirtualInheritance2 : VirtualInheritance1, virtual Base, virtual Base2 {
int vi2; int vi2;
float vi2f; float vi2f;
}; };
struct EffectivelyVirtual : virtual SingleInheritance, MultipleInheritance { struct EffectivelyVirtual : virtual SingleInheritance, MultipleInheritance {
int ev1; int ev1;
float ev1f; float ev1f;
}; };
struct PolymorphicBase { struct PolymorphicBase {
virtual ~PolymorphicBase(); virtual ~PolymorphicBase();
int pb1; int pb1;
float pb1f; float pb1f;
}; };
struct InheritsVTable : PolymorphicBase { struct InheritsVTable : PolymorphicBase {
int iv1; int iv1;
float iv1f; float iv1f;
}; };
struct IntroducesVTable : Base { struct IntroducesVTable : Base {
virtual ~IntroducesVTable(); virtual ~IntroducesVTable();
int iv2; int iv2;
float iv2f; float iv2f;
}; };
struct Left : virtual Base { struct Left : virtual Base {
int l1; int l1;
float l1f; float l1f;
}; };
struct Right : virtual Base { struct Right : virtual Base {
int r1; int r1;
float r1f; float r1f;
}; };
struct Bottom : Left, Right { struct Bottom : Left, Right {
int b1; int b1;
float b1f; float b1f;
}; };
struct DeepSingleInheritance : SingleInheritance { struct DeepSingleInheritance : SingleInheritance {
int dsi1; int dsi1;
float dsi1f; float dsi1f;
}; };
struct Incomplete; struct Incomplete;
Incomplete* p; Incomplete* p;
template<typename T> template<typename T>
struct TemplateClass : Base struct TemplateClass : Base
{ {
}; };

View File

@@ -1,102 +1,102 @@
// GOOD = at least one iteration // GOOD = at least one iteration
// BAD = possibly no iterations // BAD = possibly no iterations
void test1() { void test1() {
for (int i = 0; i < 10; i++) { // GOOD for (int i = 0; i < 10; i++) { // GOOD
} }
} }
void test2() { void test2() {
for (int i = 0, j = 1; i + j < 10; i++) { // GOOD for (int i = 0, j = 1; i + j < 10; i++) { // GOOD
} }
} }
void test3() { void test3() {
int j = 2; int j = 2;
for (int i = j = 1; i + j < 10; i++) { // GOOD for (int i = j = 1; i + j < 10; i++) { // GOOD
} }
} }
void test4() { void test4() {
int i = 2, j = 3; int i = 2, j = 3;
for (i = j = 1; i + j < 10; i++) { // GOOD for (i = j = 1; i + j < 10; i++) { // GOOD
} }
} }
void test5() { void test5() {
int i, k; int i, k;
for (i = k = 0; i < 10; i++) { // GOOD for (i = k = 0; i < 10; i++) { // GOOD
} }
} }
void test6() { void test6() {
int i = 0; int i = 0;
for (; i < 10; i++) { // GOOD for (; i < 10; i++) { // GOOD
i = 1; i = 1;
} }
} }
void test7() { void test7() {
int i = 0; int i = 0;
for (i = 1; i < 10; i++) { // GOOD for (i = 1; i < 10; i++) { // GOOD
i = 1; i = 1;
} }
} }
void test8() { void test8() {
int i = 0; int i = 0;
i = 1; i = 1;
for (; i < 10; i++) { // GOOD (NOT REPORTED) for (; i < 10; i++) { // GOOD (NOT REPORTED)
} }
} }
void test9() { void test9() {
bool done = false; bool done = false;
for (; !done; ) { // GOOD for (; !done; ) { // GOOD
done = true; done = true;
} }
} }
void test10(int i) { void test10(int i) {
bool done = false; bool done = false;
for (; i++; i < 10) { // BAD for (; i++; i < 10) { // BAD
for (; !done; ) { // BAD for (; !done; ) { // BAD
done = true; done = true;
} }
} }
} }
void test11(int i) { void test11(int i) {
for (; i++; i < 10) { // BAD for (; i++; i < 10) { // BAD
bool done = false; bool done = false;
for (; !done; ) { // GOOD for (; !done; ) { // GOOD
done = true; done = true;
} }
} }
} }
void test12(int max) { void test12(int max) {
int i, k; int i, k;
int max_index = 0; int max_index = 0;
for (i = k = 0; i < max; i++) { // BAD for (i = k = 0; i < max; i++) { // BAD
max_index = i; max_index = i;
} }
for (i = 0; i <= max_index; i++) { // BAD for (i = 0; i <= max_index; i++) { // BAD
} }
} }
void test13() { void test13() {
int i; int i;
for (i = 1; i > 0; ) { // GOOD for (i = 1; i > 0; ) { // GOOD
&i; &i;
} }
} }
void test14(bool b) { void test14(bool b) {
int i = 1; int i = 1;
while (b) { while (b) {
for (; i > 0; ) { // BAD for (; i > 0; ) { // BAD
&i; &i;
} }
} }
} }

View File

@@ -1,64 +1,64 @@
// GOOD = at least one iteration // GOOD = at least one iteration
// BAD = possibly no iterations // BAD = possibly no iterations
void test1() { void test1() {
bool done = false; bool done = false;
while (!done) { // GOOD while (!done) { // GOOD
done = true; done = true;
} }
} }
void test2() { void test2() {
bool done = true; bool done = true;
done = false; done = false;
while (!done) { // GOOD (NOT REPORTED) while (!done) { // GOOD (NOT REPORTED)
done = true; done = true;
} }
} }
void test3(int i) { void test3(int i) {
bool done = false; bool done = false;
for (; i++; i < 10) { for (; i++; i < 10) {
while (!done) { // BAD while (!done) { // BAD
done = true; done = true;
} }
} }
} }
void test4(int i) { void test4(int i) {
for (; i++; i < 10) { for (; i++; i < 10) {
bool done = false; bool done = false;
while (!done) { // GOOD while (!done) { // GOOD
done = true; done = true;
} }
} }
} }
void test5(int max) { void test5(int max) {
int i = 0, k = 0; int i = 0, k = 0;
int max_index = 0; int max_index = 0;
while (i < max) { // BAD while (i < max) { // BAD
max_index = i; max_index = i;
i++; i++;
} }
i = 0; i = 0;
while (i <= max_index) { // BAD while (i <= max_index) { // BAD
i++; i++;
} }
} }
void test6() { void test6() {
int i = 1; int i = 1;
while (i > 0) { // GOOD while (i > 0) { // GOOD
&i; &i;
} }
} }
void test7(bool b) { void test7(bool b) {
int i = 1; int i = 1;
while (b) { // BAD while (b) { // BAD
while (i > 0) { // BAD while (i > 0) { // BAD
&i; &i;
} }
} }
} }

View File

@@ -1,250 +1,250 @@
typedef unsigned short ushort; typedef unsigned short ushort;
enum E { enum E {
E0, E0,
E1 E1
}; };
enum class EC : int { enum class EC : int {
EC0, EC0,
EC1 EC1
}; };
void ArithmeticConversions() { void ArithmeticConversions() {
char c = 0; char c = 0;
unsigned char uc = 0; unsigned char uc = 0;
short s = 0; short s = 0;
unsigned short us = 0; unsigned short us = 0;
int i = 0; int i = 0;
unsigned int ui = 0; unsigned int ui = 0;
long l = 0; long l = 0;
unsigned long ul = 0; unsigned long ul = 0;
long long ll = 0; long long ll = 0;
unsigned long long ull = 0; unsigned long long ull = 0;
float f = 0; float f = 0;
double d = 0; double d = 0;
wchar_t wc = 0; wchar_t wc = 0;
E e{}; E e{};
EC ec{}; EC ec{};
c = uc; c = uc;
c = (char)uc; c = (char)uc;
c = char(uc); c = char(uc);
c = static_cast<char>(uc); c = static_cast<char>(uc);
i = s; i = s;
i = (int)s; i = (int)s;
i = int(s); i = int(s);
i = static_cast<int>(s); i = static_cast<int>(s);
us = i; us = i;
us = (unsigned short)i; us = (unsigned short)i;
us = ushort(i); us = ushort(i);
us = static_cast<unsigned short>(i); us = static_cast<unsigned short>(i);
i = d; i = d;
i = (int)d; i = (int)d;
i = int(d); i = int(d);
i = static_cast<int>(d); i = static_cast<int>(d);
f = c; f = c;
f = (float)c; f = (float)c;
f = float(c); f = float(c);
f = static_cast<float>(c); f = static_cast<float>(c);
f = d; f = d;
f = (float)d; f = (float)d;
f = float(d); f = float(d);
f = static_cast<float>(d); f = static_cast<float>(d);
d = f; d = f;
d = (double)f; d = (double)f;
d = double(f); d = double(f);
d = static_cast<double>(f); d = static_cast<double>(f);
i = E0; i = E0;
i = e; i = e;
i = static_cast<int>(EC::EC0); i = static_cast<int>(EC::EC0);
i = static_cast<int>(ec); i = static_cast<int>(ec);
e = static_cast<E>(i); e = static_cast<E>(i);
ec = static_cast<EC>(i); ec = static_cast<EC>(i);
} }
struct S { struct S {
int x; int x;
double y; double y;
}; };
void ConversionsToBool() { void ConversionsToBool() {
bool b = 0; bool b = 0;
int i = 0; int i = 0;
double d = 0; double d = 0;
void* p = nullptr; void* p = nullptr;
int S::* pmd = nullptr; int S::* pmd = nullptr;
if (b) { if (b) {
} }
else if ((bool)b) { else if ((bool)b) {
} }
else if (i) { else if (i) {
} }
else if (d) { else if (d) {
} }
else if (p) { else if (p) {
} }
else if (pmd) { else if (pmd) {
} }
} }
struct Base { struct Base {
int b1; int b1;
void BaseMethod(); void BaseMethod();
}; };
struct Middle : Base { struct Middle : Base {
int m1; int m1;
void MiddleMethod(); void MiddleMethod();
}; };
struct Derived : Middle { struct Derived : Middle {
int d1; int d1;
void DerivedMethod(); void DerivedMethod();
}; };
void HierarchyCasts() { void HierarchyCasts() {
Base b; Base b;
Middle m; Middle m;
Derived d; Derived d;
Base* pb = &b; Base* pb = &b;
Middle* pm = &m; Middle* pm = &m;
Derived* pd = &d; Derived* pd = &d;
b = m; b = m;
b = (Base)m; b = (Base)m;
b = static_cast<Base>(m); b = static_cast<Base>(m);
pb = pm; pb = pm;
pb = (Base*)pm; pb = (Base*)pm;
pb = static_cast<Base*>(pm); pb = static_cast<Base*>(pm);
pb = reinterpret_cast<Base*>(pm); pb = reinterpret_cast<Base*>(pm);
m = (Middle&)b; m = (Middle&)b;
m = static_cast<Middle&>(b); m = static_cast<Middle&>(b);
pm = (Middle*)pb; pm = (Middle*)pb;
pm = static_cast<Middle*>(pb); pm = static_cast<Middle*>(pb);
pm = reinterpret_cast<Middle*>(pb); pm = reinterpret_cast<Middle*>(pb);
b = d; b = d;
b = (Base)d; b = (Base)d;
b = static_cast<Base>(d); b = static_cast<Base>(d);
pb = pd; pb = pd;
pb = (Base*)pd; pb = (Base*)pd;
pb = static_cast<Base*>(pd); pb = static_cast<Base*>(pd);
pb = reinterpret_cast<Base*>(pd); pb = reinterpret_cast<Base*>(pd);
d = (Derived&)b; d = (Derived&)b;
d = static_cast<Derived&>(b); d = static_cast<Derived&>(b);
pd = (Derived*)pb; pd = (Derived*)pb;
pd = static_cast<Derived*>(pb); pd = static_cast<Derived*>(pb);
pd = reinterpret_cast<Derived*>(pb); pd = reinterpret_cast<Derived*>(pb);
} }
void PTMCasts() { void PTMCasts() {
int Base::* pb = &Base::b1; int Base::* pb = &Base::b1;
void (Base::* pmfb)() = &Base::BaseMethod; void (Base::* pmfb)() = &Base::BaseMethod;
int Middle::* pm = &Middle::m1; int Middle::* pm = &Middle::m1;
void (Middle::* pmfm)() = &Middle::MiddleMethod; void (Middle::* pmfm)() = &Middle::MiddleMethod;
int Derived::* pd = &Derived::d1; int Derived::* pd = &Derived::d1;
void (Derived::* pmfd)() = &Derived::DerivedMethod; void (Derived::* pmfd)() = &Derived::DerivedMethod;
pb = (int Base::*)pm; pb = (int Base::*)pm;
pmfb = (void (Base::*)())pmfm; pmfb = (void (Base::*)())pmfm;
pb = static_cast<int Base::*>(pm); pb = static_cast<int Base::*>(pm);
pmfb = static_cast<void (Base::*)()>(pmfm); pmfb = static_cast<void (Base::*)()>(pmfm);
pm = pb; pm = pb;
pmfm = pmfb; pmfm = pmfb;
pm = (int Middle::*)pb; pm = (int Middle::*)pb;
pmfm = (void (Middle::*)())pmfb; pmfm = (void (Middle::*)())pmfb;
pm = static_cast<int Middle::*>(pb); pm = static_cast<int Middle::*>(pb);
pmfm = static_cast<void (Middle::*)()>(pmfb); pmfm = static_cast<void (Middle::*)()>(pmfb);
pb = (int Base::*)pd; pb = (int Base::*)pd;
pmfb = (void (Base::*)())pmfd; pmfb = (void (Base::*)())pmfd;
pb = static_cast<int Base::*>(pd); pb = static_cast<int Base::*>(pd);
pmfb = static_cast<void (Base::*)()>(pmfd); pmfb = static_cast<void (Base::*)()>(pmfd);
pd = pb; pd = pb;
pmfd = pmfb; pmfd = pmfb;
pd = (int Derived::*)pb; pd = (int Derived::*)pb;
pmfd = (void (Derived::*)())pmfb; pmfd = (void (Derived::*)())pmfb;
pd = static_cast<int Derived::*>(pb); pd = static_cast<int Derived::*>(pb);
pmfd = static_cast<void (Derived::*)()>(pmfb); pmfd = static_cast<void (Derived::*)()>(pmfb);
} }
struct String { struct String {
String(); String();
String(const String&); String(const String&);
~String(); ~String();
}; };
void Adjust() { void Adjust() {
const String& s1 = String(); // prvalue adjustment const String& s1 = String(); // prvalue adjustment
Base b; Base b;
Derived d; Derived d;
const Base& rb = true ? b : d; // glvalue adjustment const Base& rb = true ? b : d; // glvalue adjustment
const Base& r = (Base&)s1; const Base& r = (Base&)s1;
} }
void QualificationConversions() { void QualificationConversions() {
const int* pc = nullptr; const int* pc = nullptr;
const volatile int* pcv = nullptr; const volatile int* pcv = nullptr;
pcv = pc; pcv = pc;
pc = const_cast<const int*>(pcv); pc = const_cast<const int*>(pcv);
} }
void PointerIntegralConversions() { void PointerIntegralConversions() {
void* p = nullptr; void* p = nullptr;
long n = (long)p; long n = (long)p;
n = reinterpret_cast<long>(p); n = reinterpret_cast<long>(p);
p = (void*)n; p = (void*)n;
p = reinterpret_cast<void*>(n); p = reinterpret_cast<void*>(n);
} }
struct PolymorphicBase { struct PolymorphicBase {
virtual ~PolymorphicBase(); virtual ~PolymorphicBase();
}; };
struct PolymorphicDerived : PolymorphicBase { struct PolymorphicDerived : PolymorphicBase {
}; };
void DynamicCast() { void DynamicCast() {
PolymorphicBase b; PolymorphicBase b;
PolymorphicDerived d; PolymorphicDerived d;
PolymorphicBase* pb = &b; PolymorphicBase* pb = &b;
PolymorphicDerived* pd = &d; PolymorphicDerived* pd = &d;
// These two casts were previously represented as BaseClassCasts because they were resolved at compile time, but the front-end no longer performs this optimization. // These two casts were previously represented as BaseClassCasts because they were resolved at compile time, but the front-end no longer performs this optimization.
pb = dynamic_cast<PolymorphicBase*>(pd); pb = dynamic_cast<PolymorphicBase*>(pd);
PolymorphicBase& rb = dynamic_cast<PolymorphicBase&>(d); PolymorphicBase& rb = dynamic_cast<PolymorphicBase&>(d);
pd = dynamic_cast<PolymorphicDerived*>(pb); pd = dynamic_cast<PolymorphicDerived*>(pb);
PolymorphicDerived& rd = dynamic_cast<PolymorphicDerived&>(b); PolymorphicDerived& rd = dynamic_cast<PolymorphicDerived&>(b);
} }
void FuncPtrConversions(int(*pfn)(int), void* p) { void FuncPtrConversions(int(*pfn)(int), void* p) {
p = (void*)pfn; p = (void*)pfn;
pfn = (int(*)(int))p; pfn = (int(*)(int))p;
} }
int Func(); int Func();
void ConversionsToVoid() { void ConversionsToVoid() {
int x; int x;
(void)x; (void)x;
static_cast<void>(x); static_cast<void>(x);
(void)Func(); (void)Func();
static_cast<void>(Func()); static_cast<void>(Func());
(void)1; (void)1;
static_cast<void>(1); static_cast<void>(1);
} }

View File

@@ -45,53 +45,53 @@ private:
int xs[4]; int xs[4];
}; };
struct A { struct A {
A(int); A(int);
}; };
struct B { struct B {
B(int); B(int);
}; };
struct C { struct C {
C(int); C(int);
}; };
struct MultipleBases : A, B, C { struct MultipleBases : A, B, C {
int x; int x;
int y; int y;
int z; int z;
MultipleBases() : MultipleBases() :
z(5), z(5),
B(1), B(1),
x(3), x(3),
A(0), A(0),
C(2), C(2),
y(4) { y(4) {
} }
}; };
struct VB { struct VB {
VB(); VB();
VB(int); VB(int);
~VB(); ~VB();
}; };
struct VD : virtual VB { struct VD : virtual VB {
}; };
struct VirtualAndNonVirtual : VD, VB { struct VirtualAndNonVirtual : VD, VB {
VirtualAndNonVirtual() { VirtualAndNonVirtual() {
} }
~VirtualAndNonVirtual() { ~VirtualAndNonVirtual() {
} }
}; };
struct AllYourVirtualBaseAreBelongToUs : VD, VirtualAndNonVirtual, virtual VB { struct AllYourVirtualBaseAreBelongToUs : VD, VirtualAndNonVirtual, virtual VB {
AllYourVirtualBaseAreBelongToUs() : AllYourVirtualBaseAreBelongToUs() :
VB(5) { VB(5) {
} }
~AllYourVirtualBaseAreBelongToUs() { ~AllYourVirtualBaseAreBelongToUs() {
} }
}; };

View File

@@ -1,10 +1,10 @@
// src5.cpp // src5.cpp
#include "src5.fwd.hpp" #include "src5.fwd.hpp"
template<class elem> template<class elem>
class my_istream { class my_istream {
}; };
template <> template <>
class my_istream<char>; class my_istream<char>;

View File

@@ -1,8 +1,8 @@
// src5.fwd.hpp // src5.fwd.hpp
#ifndef SRC5_FWD_HPP #ifndef SRC5_FWD_HPP
#define SRC5_FWD_HPP #define SRC5_FWD_HPP
template<class elem> class my_istream; template<class elem> class my_istream;
#endif // SRC5_FWD_HPP #endif // SRC5_FWD_HPP

View File

@@ -1,5 +1,5 @@
// src6.cpp // src6.cpp
#include "src5.fwd.hpp" #include "src5.fwd.hpp"
my_istream<char> *mis_c; my_istream<char> *mis_c;

View File

@@ -1,28 +1,28 @@
class A { class A {
public: public:
A() {} A() {}
}; };
A a; A a;
void f() {} void f() {}
class Test { class Test {
A aa; A aa;
void fa() {} void fa() {}
void test() { void test() {
void (*fptr)(); void (*fptr)();
void (Test::*mfptr)(); void (Test::*mfptr)();
void *ptr; void *ptr;
ptr = &a; ptr = &a;
ptr = &aa; ptr = &aa;
fptr = f; // same as below fptr = f; // same as below
fptr = &f; // same as above fptr = &f; // same as above
mfptr = &Test::fa; mfptr = &Test::fa;
} }
}; };

View File

@@ -1,28 +1,28 @@
class Friend1 { class Friend1 {
public: public:
void f(); void f();
protected: protected:
void g(); void g();
private: private:
void h(); void h();
}; };
class Friend2 { class Friend2 {
public: public:
void f(); void f();
protected: protected:
void g(); void g();
private: private:
void h(); void h();
}; };
void Friend2::f() { void Friend2::f() {
} }
void friendFunc() {} void friendFunc() {}
class C { class C {
friend class Friend1; friend class Friend1;
friend void Friend2::f(); friend void Friend2::f();
friend void friendFunc(); friend void friendFunc();
}; };

View File

@@ -1,31 +1,31 @@
//references(UserType) //references(UserType)
class A { class A {
public: public:
A() {} A() {}
}; };
int f() { int f() {
void *a_ptr = new A(); //match (1 call) void *a_ptr = new A(); //match (1 call)
A a = A(); // match (1 call) A a = A(); // match (1 call)
return 1; return 1;
} }
//calls(Function) //calls(Function)
int g() {return 0;} int g() {return 0;}
extern int h(); extern int h();
int x = g(); //match int x = g(); //match
int y = x + g(); //match (1 call, 1 access) int y = x + g(); //match (1 call, 1 access)
int z = x + g() + h(); //match(2 calls, 1 access) int z = x + g() + h(); //match(2 calls, 1 access)
//accesses(Variable) //accesses(Variable)
int i = 1; int i = 1;
int j = i; //match (1 access) int j = i; //match (1 access)
A a; //match(1 call) A a; //match(1 call)
A ax = A(); //match (1 call) A ax = A(); //match (1 call)
A aax = ax; //match (1 access) A aax = ax; //match (1 access)
//array initialization //array initialization
int myIntArray[5] = {i, 0, 0, 0, 0}; //match(1 access) int myIntArray[5] = {i, 0, 0, 0, 0}; //match(1 access)
A myObjectArray[3]; //match(1 call) A myObjectArray[3]; //match(1 call)

View File

@@ -1,89 +1,89 @@
const int c = 1; const int c = 1;
int v = 1; int v = 1;
int one() {return 1;} int one() {return 1;}
void myNormalFunction() void myNormalFunction()
{ {
static int static_1 = 1; static int static_1 = 1;
static int static_c = c; static int static_c = c;
static int static_v = v; static int static_v = v;
static int static_one = one(); static int static_one = one();
int local_1 = 1; int local_1 = 1;
int local_c = c; int local_c = c;
int local_v = v; int local_v = v;
int local_one = one(); int local_one = one();
} }
template<class T> void myTemplateFunction() template<class T> void myTemplateFunction()
{ {
static int static_int_1 = 1; static int static_int_1 = 1;
static int static_int_c = c; // [initializer is not populated] static int static_int_c = c; // [initializer is not populated]
static int static_int_v = v; // [initializer is not populated] static int static_int_v = v; // [initializer is not populated]
static int static_int_one = one(); // [initializer is not populated] static int static_int_one = one(); // [initializer is not populated]
static T static_t_1 = 1; // [initializer is not populated] static T static_t_1 = 1; // [initializer is not populated]
static T static_t_c = c; // [initializer is not populated] static T static_t_c = c; // [initializer is not populated]
static T static_t_v = v; // [initializer is not populated] static T static_t_v = v; // [initializer is not populated]
static T static_t_one = one(); // [initializer is not populated] static T static_t_one = one(); // [initializer is not populated]
int local_int_1 = 1; int local_int_1 = 1;
int local_int_c = c; int local_int_c = c;
int local_int_v = v; int local_int_v = v;
int local_int_one = one(); int local_int_one = one();
T local_t_1 = 1; T local_t_1 = 1;
T local_t_c = c; T local_t_c = c;
T local_t_v = v; T local_t_v = v;
T local_t_one = one(); T local_t_one = one();
} }
template<class T> class myTemplateClass template<class T> class myTemplateClass
{ {
public: public:
void myMethod() void myMethod()
{ {
static int static_int_1 = 1; static int static_int_1 = 1;
static int static_int_c = c; // [initializer is not populated] static int static_int_c = c; // [initializer is not populated]
static int static_int_v = v; // [initializer is not populated] static int static_int_v = v; // [initializer is not populated]
static int static_int_one = one(); // [initializer is not populated] static int static_int_one = one(); // [initializer is not populated]
static T static_t_1 = 1; // [initializer is not populated] static T static_t_1 = 1; // [initializer is not populated]
static T static_t_c = c; // [initializer is not populated] static T static_t_c = c; // [initializer is not populated]
static T static_t_v = v; // [initializer is not populated] static T static_t_v = v; // [initializer is not populated]
static T static_t_one = one(); // [initializer is not populated] static T static_t_one = one(); // [initializer is not populated]
int local_int_1 = 1; int local_int_1 = 1;
int local_int_c = c; int local_int_c = c;
int local_int_v = v; int local_int_v = v;
int local_int_one = one(); int local_int_one = one();
T local_t_1 = 1; T local_t_1 = 1;
T local_t_c = c; T local_t_c = c;
T local_t_v = v; T local_t_v = v;
T local_t_one = one(); T local_t_one = one();
} }
}; };
enum myEnum enum myEnum
{ {
MYENUM_CONST MYENUM_CONST
}; };
template<class T> void myTemplateFunction2(int a = 1, T b = 2) template<class T> void myTemplateFunction2(int a = 1, T b = 2)
{ {
static int static_int_zero = 0; static int static_int_zero = 0;
static int static_int_ec = MYENUM_CONST; static int static_int_ec = MYENUM_CONST;
static int static_int_expr = v + 1; static int static_int_expr = v + 1;
static int *static_int_addr = &v; static int *static_int_addr = &v;
static int static_int_sizeof_v = sizeof(v); static int static_int_sizeof_v = sizeof(v);
static int static_int_sizeof_t = sizeof(T); static int static_int_sizeof_t = sizeof(T);
static T static_t_zero = 0; static T static_t_zero = 0;
static T static_t_ec = MYENUM_CONST; static T static_t_ec = MYENUM_CONST;
static T static_t_expr = v + 1; static T static_t_expr = v + 1;
static T *static_t_addr = &v; static T *static_t_addr = &v;
static T static_t_sizeof_v = sizeof(v); static T static_t_sizeof_v = sizeof(v);
static T static_t_sizeof_t = sizeof(T); static T static_t_sizeof_t = sizeof(T);
static int static_int_c1 = c; static int static_int_c1 = c;
static int static_int_c2=c; static int static_int_c2=c;
{ {
static int static_int_v2 = v; static int static_int_v2 = v;
} }
} }

View File

@@ -1,74 +1,74 @@
namespace ns2 { namespace ns2 {
const int c = 1; const int c = 1;
int v = 1; int v = 1;
int one() {return 1;} int one() {return 1;}
void myNormalFunction() void myNormalFunction()
{ {
static int static_1 = 1; static int static_1 = 1;
static int static_c = c; static int static_c = c;
static int static_v = v; static int static_v = v;
static int static_one = one(); static int static_one = one();
int local_1 = 1; int local_1 = 1;
int local_c = c; int local_c = c;
int local_v = v; int local_v = v;
int local_one = one(); int local_one = one();
} }
template<class T> void myTemplateFunction() template<class T> void myTemplateFunction()
{ {
static int static_int_1 = 1; static int static_int_1 = 1;
static int static_int_c = c; // [initializer is not populated] static int static_int_c = c; // [initializer is not populated]
static int static_int_v = v; // [initializer is not populated] static int static_int_v = v; // [initializer is not populated]
static int static_int_one = one(); // [initializer is not populated] static int static_int_one = one(); // [initializer is not populated]
static T static_t_1 = 1; // [initializer is not populated] static T static_t_1 = 1; // [initializer is not populated]
static T static_t_c = c; // [initializer is not populated] static T static_t_c = c; // [initializer is not populated]
static T static_t_v = v; // [initializer is not populated] static T static_t_v = v; // [initializer is not populated]
static T static_t_one = one(); // [initializer is not populated] static T static_t_one = one(); // [initializer is not populated]
int local_int_1 = 1; int local_int_1 = 1;
int local_int_c = c; int local_int_c = c;
int local_int_v = v; int local_int_v = v;
int local_int_one = one(); int local_int_one = one();
T local_t_1 = 1; T local_t_1 = 1;
T local_t_c = c; T local_t_c = c;
T local_t_v = v; T local_t_v = v;
T local_t_one = one(); T local_t_one = one();
} }
template<class T> class myTemplateClass template<class T> class myTemplateClass
{ {
public: public:
void myMethod() void myMethod()
{ {
static int static_int_1 = 1; static int static_int_1 = 1;
static int static_int_c = c; // [initializer is not populated] static int static_int_c = c; // [initializer is not populated]
static int static_int_v = v; // [initializer is not populated] static int static_int_v = v; // [initializer is not populated]
static int static_int_one = one(); // [initializer is not populated] static int static_int_one = one(); // [initializer is not populated]
static T static_t_1 = 1; // [initializer is not populated] static T static_t_1 = 1; // [initializer is not populated]
static T static_t_c = c; // [initializer is not populated] static T static_t_c = c; // [initializer is not populated]
static T static_t_v = v; // [initializer is not populated] static T static_t_v = v; // [initializer is not populated]
static T static_t_one = one(); // [initializer is not populated] static T static_t_one = one(); // [initializer is not populated]
int local_int_1 = 1; int local_int_1 = 1;
int local_int_c = c; int local_int_c = c;
int local_int_v = v; int local_int_v = v;
int local_int_one = one(); int local_int_one = one();
T local_t_1 = 1; T local_t_1 = 1;
T local_t_c = c; T local_t_c = c;
T local_t_v = v; T local_t_v = v;
T local_t_one = one(); T local_t_one = one();
} }
}; };
void testFunc() void testFunc()
{ {
// instantiate the templates // instantiate the templates
myTemplateFunction<int>(); myTemplateFunction<int>();
{ {
myTemplateClass<int> mtc; myTemplateClass<int> mtc;
mtc.myMethod(); mtc.myMethod();
} }
} }
} }

View File

@@ -1,9 +1,9 @@
class C { class C {
C() {} C() {}
}; };
typedef C CC; typedef C CC;
CC** f() { CC** f() {
return 0; return 0;
} }

View File

@@ -1,15 +1,15 @@
const int j = 0; const int j = 0;
enum Day { sun, mon, tue, wed, thu, fri, sat }; enum Day { sun, mon, tue, wed, thu, fri, sat };
enum Day2 { sun2 = j, mon2, tue2 }; enum Day2 { sun2 = j, mon2, tue2 };
enum Flag { b = 'a', c = 'b', d = 'd' }; enum Flag { b = 'a', c = 'b', d = 'd' };
Day& operator++(Day& d) Day& operator++(Day& d)
{ {
int i = d; int i = d;
Flag f = Flag(7); Flag f = Flag(7);
Flag g = Flag(8); Flag g = Flag(8);
//const int *p = &sat; //const int *p = &sat;
Day2 d2 = (Day2)d; Day2 d2 = (Day2)d;
return d = (sat==d) ? sun: Day(d+1); return d = (sat==d) ? sun: Day(d+1);
} }

View File

@@ -1,14 +1,14 @@
int main() int main()
{ {
int x; int x;
if (x == 1) {} if (x == 1) {}
if (x != 1) {} if (x != 1) {}
if (x < 1) {} if (x < 1) {}
if (x > 1) {} if (x > 1) {}
if (x <= 1) {} if (x <= 1) {}
if (x >= 1) {} if (x >= 1) {}
return 0; return 0;
} }

View File

@@ -1,15 +1,15 @@
int main() int main()
{ {
int i; int i;
int *ip; int *ip;
i = +(-1); i = +(-1);
i++; i++;
ip = &i; ip = &i;
*ip--; *ip--;
++i; ++i;
--i; --i;
return 0; return 0;
} }

Some files were not shown because too many files have changed in this diff Show More