mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge branch 'master' into master
This commit is contained in:
@@ -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
63
.gitattributes
vendored
@@ -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
4
.gitignore
vendored
@@ -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
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
@@ -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()
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
void f() {
|
void f() {
|
||||||
static int i = 0; //i is unused
|
static int i = 0; //i is unused
|
||||||
...
|
...
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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[]'
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
int foo = 1;
|
int foo = 1;
|
||||||
... //foo is unused
|
... //foo is unused
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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);
|
||||||
|
|||||||
@@ -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)
|
||||||
//...
|
//...
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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'
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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 *)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
LPMALLOC pMalloc;
|
||||||
|
HRESULT hr = CoGetMalloc(1, &pMalloc);
|
||||||
|
|
||||||
|
if (!hr)
|
||||||
|
{
|
||||||
|
// code ...
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
71
cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql
Normal file
71
cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql
Normal 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
|
||||||
@@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// common.h
|
// common.h
|
||||||
|
|
||||||
#include "nameclash.h"
|
#include "nameclash.h"
|
||||||
|
|
||||||
static int myArray[sizeof(MYTYPE)];
|
static int myArray[sizeof(MYTYPE)];
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
// defines_issue.h
|
// defines_issue.h
|
||||||
|
|
||||||
#include DEFINED_HEADER
|
#include DEFINED_HEADER
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
// nameclash.h
|
// nameclash.h
|
||||||
|
|
||||||
#include_next "nameclash.h"
|
#include_next "nameclash.h"
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
// subdir1/nameclash.h
|
// subdir1/nameclash.h
|
||||||
|
|
||||||
typedef long long int MYTYPE;
|
typedef long long int MYTYPE;
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
// subdir2/nameclash.h
|
// subdir2/nameclash.h
|
||||||
|
|
||||||
typedef char MYTYPE;
|
typedef char MYTYPE;
|
||||||
@@ -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];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
|
|
||||||
extern void swap(int*, int*);
|
extern void swap(int*, int*);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -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>;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
class C {
|
class C {
|
||||||
C() {}
|
C() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef C CC;
|
typedef C CC;
|
||||||
|
|
||||||
CC** f() {
|
CC** f() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
Reference in New Issue
Block a user