diff --git a/.editorconfig b/.editorconfig index decc2081a24..270106b1fac 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,2 +1,2 @@ -[*.{ql,qll,qlref,dbscheme,qhelp,html,js,mjs,ts,json,yml}] -end_of_line = lf +[*] +end_of_line = lf diff --git a/.gitattributes b/.gitattributes index ec825a38b57..626c5a297c8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,23 +1,48 @@ -# The following file types will be normalized to LF line endings in the Git -# database, and will keep those LF line endings in the working tree even on -# Windows. Any other files will have whatever line endings they had when they -# 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): +# Text files will be normalized to LF line endings in the Git database, and will keep those LF line +# endings in the working tree even on Windows. If you make changes 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 status [just to show what files were renormalized] # git commit -m "Normalize line endings" -# -# Also, please update .editorconfig to handle any new entries as well. -*.ql eol=lf -*.qll eol=lf -*.qlref eol=lf -*.dbscheme eol=lf -*.qhelp eol=lf -*.html eol=lf -*.js eol=lf -*.mjs eol=lf -*.ts eol=lf -*.json eol=lf -*.yml eol=lf + +# Anything Git auto-detects as text gets normalized and checked out as LF +* text=auto eol=lf + +# Explicitly set a bunch of known extensions to text, in case auto detection gets confused. +*.ql text +*.qll text +*.qlref text +*.dbscheme text +*.qhelp text +*.html text +*.htm text +*.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 diff --git a/.gitignore b/.gitignore index effd82ac428..7e82b2f488c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,4 @@ /.vs/ql/v15/Browse.VC.opendb /.vs/ql/v15/Browse.VC.db /.vs/ProjectSettings.json -/.vs/ql5/v15/Browse.VC.opendb -/.vs/ql5/v15/Browse.VC.db -/.vs/ql5/v15/.suo + diff --git a/change-notes/1.19/analysis-cpp.md b/change-notes/1.19/analysis-cpp.md index 17a165e5928..5a3340603c8 100644 --- a/change-notes/1.19/analysis-cpp.md +++ b/change-notes/1.19/analysis-cpp.md @@ -1,20 +1,20 @@ -# Improvements to C/C++ analysis - -## General improvements - -## New queries - -| **Query** | **Tags** | **Purpose** | -|-----------------------------|-----------|--------------------------------------------------------------------| -| *@name of query (Query ID)* | *Tags* |*Aim of the new query and whether it is enabled by default or not* | - -## Changes to existing queries - -| **Query** | **Expected impact** | **Change** | -|----------------------------|------------------------|------------------------------------------------------------------| -| *@name of query (Query ID)*| *Impact on results* | *How/why the query has changed* | - - -## Changes to QL libraries - -* Added a hash consing library for structural comparison of expressions. +# Improvements to C/C++ analysis + +## General improvements + +## New queries + +| **Query** | **Tags** | **Purpose** | +|-----------------------------|-----------|--------------------------------------------------------------------| +| *@name of query (Query ID)* | *Tags* |*Aim of the new query and whether it is enabled by default or not* | + +## Changes to existing queries + +| **Query** | **Expected impact** | **Change** | +|----------------------------|------------------------|------------------------------------------------------------------| +| Resource not released in destructor | Fewer false positive results | Placement new is now excluded from the query. | + + +## Changes to QL libraries + +* Added a hash consing library for structural comparison of expressions. diff --git a/change-notes/1.19/analysis-javascript.md b/change-notes/1.19/analysis-javascript.md index 4415af95d30..82077d8a8e4 100644 --- a/change-notes/1.19/analysis-javascript.md +++ b/change-notes/1.19/analysis-javascript.md @@ -22,5 +22,6 @@ | 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. | | 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 diff --git a/cpp/config/suites/security/cwe-120 b/cpp/config/suites/security/cwe-120 index 0343041d79e..483958868eb 100644 --- a/cpp/config/suites/security/cwe-120 +++ b/cpp/config/suites/security/cwe-120 @@ -1,13 +1,13 @@ -# CWE-120: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow') -+ semmlecode-cpp-queries/Security/CWE/CWE-120/UnboundedWrite.ql: /CWE/CWE-120 - @name Unbounded write (CWE-120) -+ semmlecode-cpp-queries/Security/CWE/CWE-120/BadlyBoundedWrite.ql: /CWE/CWE-120 - @name Badly bounded write (CWE-120) -+ semmlecode-cpp-queries/Security/CWE/CWE-120/OverrunWrite.ql: /CWE/CWE-120 - @name Potentially overrunning write (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) -+ semmlecode-cpp-queries/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql: /CWE/CWE-120 - @name Array offset used before range check (CWE-120) -+ semmlecode-cpp-queries/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql: /CWE/CWE-120 - @name Potentially unsafe use of strcat (CWE-120) +# CWE-120: Buffer Copy without Checking Size of Input ('Classic Buffer Overflow') ++ semmlecode-cpp-queries/Security/CWE/CWE-120/UnboundedWrite.ql: /CWE/CWE-120 + @name Unbounded write (CWE-120) ++ semmlecode-cpp-queries/Security/CWE/CWE-120/BadlyBoundedWrite.ql: /CWE/CWE-120 + @name Badly bounded write (CWE-120) ++ semmlecode-cpp-queries/Security/CWE/CWE-120/OverrunWrite.ql: /CWE/CWE-120 + @name Potentially overrunning write (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) ++ semmlecode-cpp-queries/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql: /CWE/CWE-120 + @name Array offset used before range check (CWE-120) ++ semmlecode-cpp-queries/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql: /CWE/CWE-120 + @name Potentially unsafe use of strcat (CWE-120) diff --git a/cpp/config/suites/security/cwe-121 b/cpp/config/suites/security/cwe-121 index c9f922d8c55..66c4da6b08d 100644 --- a/cpp/config/suites/security/cwe-121 +++ b/cpp/config/suites/security/cwe-121 @@ -1,3 +1,3 @@ -# CWE-121: Stack-based Buffer Overflow -+ semmlecode-cpp-queries/Security/CWE/CWE-121/UnterminatedVarargsCall.ql: /CWE/CWE-121 - @name Unterminated variadic call (CWE-121) +# CWE-121: Stack-based Buffer Overflow ++ semmlecode-cpp-queries/Security/CWE/CWE-121/UnterminatedVarargsCall.ql: /CWE/CWE-121 + @name Unterminated variadic call (CWE-121) diff --git a/cpp/config/suites/security/cwe-131 b/cpp/config/suites/security/cwe-131 index ae675145902..5bbdf081b86 100644 --- a/cpp/config/suites/security/cwe-131 +++ b/cpp/config/suites/security/cwe-131 @@ -1,7 +1,7 @@ -# CWE-131: Incorrect Calculation of Buffer Size -+ semmlecode-cpp-queries/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql: /CWE/CWE-131 - @name No space for zero terminator (CWE-131) -+ semmlecode-cpp-queries/Critical/SizeCheck.ql: /CWE/CWE-131 - @name Not enough memory allocated for pointer type (CWE-131) -+ semmlecode-cpp-queries/Critical/SizeCheck2.ql: /CWE/CWE-131 - @name Not enough memory allocated for array of pointer type (CWE-131) +# CWE-131: Incorrect Calculation of Buffer Size ++ semmlecode-cpp-queries/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql: /CWE/CWE-131 + @name No space for zero terminator (CWE-131) ++ semmlecode-cpp-queries/Critical/SizeCheck.ql: /CWE/CWE-131 + @name Not enough memory allocated for pointer type (CWE-131) ++ semmlecode-cpp-queries/Critical/SizeCheck2.ql: /CWE/CWE-131 + @name Not enough memory allocated for array of pointer type (CWE-131) diff --git a/cpp/config/suites/security/cwe-134 b/cpp/config/suites/security/cwe-134 index b6c1d5411a5..060ebbfa70b 100644 --- a/cpp/config/suites/security/cwe-134 +++ b/cpp/config/suites/security/cwe-134 @@ -1,13 +1,13 @@ -# CWE-134: Uncontrolled Format String -+ semmlecode-cpp-queries/Likely Bugs/Format/NonConstantFormat.ql: /CWE/CWE-134 - @name Non-constant format string (CWE-134) -# This one runs out of memory. See ODASA-608. -#+ semmlecode-cpp-queries/PointsTo/TaintedFormatStrings.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) -+ semmlecode-cpp-queries/Likely Bugs/Format/WrongTypeFormatArguments.ql: /CWE/CWE-134 - @name Wrong type of arguments to formatting function (CWE-134) -+ semmlecode-cpp-queries/Security/CWE/CWE-134/UncontrolledFormatString.ql: /CWE/CWE-134 - @name Uncontrolled format string (CWE-134) -+ semmlecode-cpp-queries/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql: /CWE/CWE-134 - @name Uncontrolled format string (through global variable) (CWE-134) +# CWE-134: Uncontrolled Format String ++ semmlecode-cpp-queries/Likely Bugs/Format/NonConstantFormat.ql: /CWE/CWE-134 + @name Non-constant format string (CWE-134) +# This one runs out of memory. See ODASA-608. +#+ semmlecode-cpp-queries/PointsTo/TaintedFormatStrings.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) ++ semmlecode-cpp-queries/Likely Bugs/Format/WrongTypeFormatArguments.ql: /CWE/CWE-134 + @name Wrong type of arguments to formatting function (CWE-134) ++ semmlecode-cpp-queries/Security/CWE/CWE-134/UncontrolledFormatString.ql: /CWE/CWE-134 + @name Uncontrolled format string (CWE-134) ++ semmlecode-cpp-queries/Security/CWE/CWE-134/UncontrolledFormatStringThroughGlobalVar.ql: /CWE/CWE-134 + @name Uncontrolled format string (through global variable) (CWE-134) diff --git a/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyDependencies.cpp b/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyDependencies.cpp index fea666c554d..4a056489271 100644 --- a/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyDependencies.cpp +++ b/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyDependencies.cpp @@ -1,17 +1,17 @@ -// 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 -#include -#include // contains non-static global myfile_err - -extern int myfile_err; // this external declaration adds a dependency on myfile.h - -class C { -public: - C() { - // one dependency for printf: - printf("Hello world!"); - // one dependency for FILE type, and one for NULL macro: - FILE fp = NULL; - } -}; - +// 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 +#include +#include // contains non-static global myfile_err + +extern int myfile_err; // this external declaration adds a dependency on myfile.h + +class C { +public: + C() { + // one dependency for printf: + printf("Hello world!"); + // one dependency for FILE type, and one for NULL macro: + FILE fp = NULL; + } +}; + diff --git a/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.cpp b/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.cpp index 0b576cc29b0..987255a46d6 100644 --- a/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.cpp +++ b/cpp/ql/src/Architecture/Refactoring Opportunities/ClassesWithManyFields.cpp @@ -1,20 +1,20 @@ -//This struct contains 30 fields. -struct MyParticle { - bool isActive; - int priority; - - float x, y, z; - float dx, dy, dz; - float ddx, ddy, ddz; - bool isCollider; - - int age, maxAge; - float size1, size2; - - bool hasColor; - unsigned char r1, g1, b1, a1; - unsigned char r2, g2, b2, a2; - - class texture *tex; - float u1, v1, u2, v2; -}; +//This struct contains 30 fields. +struct MyParticle { + bool isActive; + int priority; + + float x, y, z; + float dx, dy, dz; + float ddx, ddy, ddz; + bool isCollider; + + int age, maxAge; + float size1, size2; + + bool hasColor; + unsigned char r1, g1, b1, a1; + unsigned char r2, g2, b2, a2; + + class texture *tex; + float u1, v1, u2, v2; +}; diff --git a/cpp/ql/src/Architecture/Refactoring Opportunities/FunctionsWithManyParameters.cpp b/cpp/ql/src/Architecture/Refactoring Opportunities/FunctionsWithManyParameters.cpp index 624226bff6a..80d2c503feb 100644 --- a/cpp/ql/src/Architecture/Refactoring Opportunities/FunctionsWithManyParameters.cpp +++ b/cpp/ql/src/Architecture/Refactoring Opportunities/FunctionsWithManyParameters.cpp @@ -1,8 +1,8 @@ -// this example has 15 parameters. -void fillRect(int x, int y, int w, int h, - int r1, int g1, int b1, int a1, - int r2, int g2, int b2, int a2, - gradient_type grad, unsigned int flags, bool border) -{ - // ... -} +// this example has 15 parameters. +void fillRect(int x, int y, int w, int h, + int r1, int g1, int b1, int a1, + int r2, int g2, int b2, int a2, + gradient_type grad, unsigned int flags, bool border) +{ + // ... +} diff --git a/cpp/ql/src/Best Practices/ComplexCondition.cpp b/cpp/ql/src/Best Practices/ComplexCondition.cpp index 8a8638c5bbe..fba51491990 100644 --- a/cpp/ql/src/Best Practices/ComplexCondition.cpp +++ b/cpp/ql/src/Best Practices/ComplexCondition.cpp @@ -1,13 +1,13 @@ -//This condition is too complex and can be improved by using local variables -bool accept_message = - (message_type == CONNECT && _state != CONNECTED) || - (message_type == DISCONNECT && _state == CONNECTED) || - (message_type == DATA && _state == CONNECTED); - -//This condition is acceptable, as all the logical operators are of the same type (&&) -bool valid_connect = - message_type == CONNECT && - _state != CONNECTED && - time_since_prev_connect > MAX_CONNECT_INTERVAL && - message_length <= MAX_PACKET_SIZE && +//This condition is too complex and can be improved by using local variables +bool accept_message = + (message_type == CONNECT && _state != CONNECTED) || + (message_type == DISCONNECT && _state == CONNECTED) || + (message_type == DATA && _state == CONNECTED); + +//This condition is acceptable, as all the logical operators are of the same type (&&) +bool valid_connect = + message_type == CONNECT && + _state != CONNECTED && + time_since_prev_connect > MAX_CONNECT_INTERVAL && + message_length <= MAX_PACKET_SIZE && checksum(message) == get_checksum_field(message); \ No newline at end of file diff --git a/cpp/ql/src/Best Practices/Hiding/DeclarationHidesParameter.cpp b/cpp/ql/src/Best Practices/Hiding/DeclarationHidesParameter.cpp index 687129d8815..374a3290ec7 100644 --- a/cpp/ql/src/Best Practices/Hiding/DeclarationHidesParameter.cpp +++ b/cpp/ql/src/Best Practices/Hiding/DeclarationHidesParameter.cpp @@ -1,6 +1,6 @@ -void f(int i) { - for (int i = 0; i < 10; ++i) { //the loop variable hides the parameter to f() - ... - } -} - +void f(int i) { + for (int i = 0; i < 10; ++i) { //the loop variable hides the parameter to f() + ... + } +} + diff --git a/cpp/ql/src/Best Practices/Hiding/DeclarationHidesVariable.cpp b/cpp/ql/src/Best Practices/Hiding/DeclarationHidesVariable.cpp index bc96def17df..7cfe4617035 100644 --- a/cpp/ql/src/Best Practices/Hiding/DeclarationHidesVariable.cpp +++ b/cpp/ql/src/Best Practices/Hiding/DeclarationHidesVariable.cpp @@ -1,12 +1,12 @@ -void f() { - int i = 10; - - 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 - ... - } -} +void f() { + int i = 10; + + 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 + ... + } +} diff --git a/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.cpp b/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.cpp index 61590c86011..89c473561a8 100644 --- a/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.cpp +++ b/cpp/ql/src/Best Practices/Hiding/LocalVariableHidesGlobalVariable.cpp @@ -1,12 +1,12 @@ -int i = 10; - -void f() { - 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 = 10; + +void f() { + 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 + ... + } +} diff --git a/cpp/ql/src/Best Practices/Likely Errors/EmptyBlock.cpp b/cpp/ql/src/Best Practices/Likely Errors/EmptyBlock.cpp index 547810752ec..a0a4c2d64ac 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/EmptyBlock.cpp +++ b/cpp/ql/src/Best Practices/Likely Errors/EmptyBlock.cpp @@ -1,9 +1,9 @@ -void f(int i) { - if (i == 10); //empty then block - ... //won't be part of the if statement - - if (i == 12) { - ... - } else { //empty else block, most likely a mistake - } -} +void f(int i) { + if (i == 10); //empty then block + ... //won't be part of the if statement + + if (i == 12) { + ... + } else { //empty else block, most likely a mistake + } +} diff --git a/cpp/ql/src/Best Practices/Likely Errors/Slicing.cpp b/cpp/ql/src/Best Practices/Likely Errors/Slicing.cpp index 09d1f414e5d..538516964a7 100644 --- a/cpp/ql/src/Best Practices/Likely Errors/Slicing.cpp +++ b/cpp/ql/src/Best Practices/Likely Errors/Slicing.cpp @@ -1,43 +1,43 @@ -static int idctr = 0; -//Basic connection with id -class Connection { -public: - int connId; - virtual void print_info() { - cout << "id: " << connId << "\n"; - } - Connection() { - connId = idctr++; - } -}; - -//Adds counters, and an overriding print_info -class MeteredConnection : public Connection { -public: - int txCtr; - int rxCtr; - MeteredConnection() { - txCtr = 0; - rxCtr = 0; - } - virtual void print_info() { - cout << "id: " << connId << "\n" << "tx/rx: " << txCtr << "/" << rxCtr << "\n"; - } -}; - -int main(int argc, char* argv[]) { - Connection conn; - MeteredConnection m_conn; - - Connection curr_conn = conn; - curr_conn.print_info(); - curr_conn = m_conn; //Wrong: Derived MetricConnection assigned to Connection - //variable, will slice off the counters and the overriding print_info - curr_conn.print_info(); //Will not print the counters. - - Connection* curr_pconn = &conn; - curr_pconn->print_info(); - curr_pconn = &m_conn; //Correct: Pointer assigned to address of the MetricConnection. - //Counters and virtual functions remain intact. - curr_pconn->print_info(); //Will call the correct method MeteredConnection::print_info -} +static int idctr = 0; +//Basic connection with id +class Connection { +public: + int connId; + virtual void print_info() { + cout << "id: " << connId << "\n"; + } + Connection() { + connId = idctr++; + } +}; + +//Adds counters, and an overriding print_info +class MeteredConnection : public Connection { +public: + int txCtr; + int rxCtr; + MeteredConnection() { + txCtr = 0; + rxCtr = 0; + } + virtual void print_info() { + cout << "id: " << connId << "\n" << "tx/rx: " << txCtr << "/" << rxCtr << "\n"; + } +}; + +int main(int argc, char* argv[]) { + Connection conn; + MeteredConnection m_conn; + + Connection curr_conn = conn; + curr_conn.print_info(); + curr_conn = m_conn; //Wrong: Derived MetricConnection assigned to Connection + //variable, will slice off the counters and the overriding print_info + curr_conn.print_info(); //Will not print the counters. + + Connection* curr_pconn = &conn; + curr_pconn->print_info(); + curr_pconn = &m_conn; //Correct: Pointer assigned to address of the MetricConnection. + //Counters and virtual functions remain intact. + curr_pconn->print_info(); //Will call the correct method MeteredConnection::print_info +} diff --git a/cpp/ql/src/Best Practices/Magic Constants/MagicConstantsNumbers.cpp b/cpp/ql/src/Best Practices/Magic Constants/MagicConstantsNumbers.cpp index f637c8d68e5..98f830132eb 100644 --- a/cpp/ql/src/Best Practices/Magic Constants/MagicConstantsNumbers.cpp +++ b/cpp/ql/src/Best Practices/Magic Constants/MagicConstantsNumbers.cpp @@ -1,16 +1,16 @@ -void sanitize(Fields[] record) { - //The number of fields here can be put in a const - for (fieldCtr = 0; field < 7; field++) { - sanitize(fields[fieldCtr]); - } -} - -#define NUM_FIELDS 7 - -void process(Fields[] record) { - //This avoids using a magic constant by using the macro instead - for (fieldCtr = 0; field < NUM_FIELDS; field++) { - process(fields[fieldCtr]); - } -} - +void sanitize(Fields[] record) { + //The number of fields here can be put in a const + for (fieldCtr = 0; field < 7; field++) { + sanitize(fields[fieldCtr]); + } +} + +#define NUM_FIELDS 7 + +void process(Fields[] record) { + //This avoids using a magic constant by using the macro instead + for (fieldCtr = 0; field < NUM_FIELDS; field++) { + process(fields[fieldCtr]); + } +} + diff --git a/cpp/ql/src/Best Practices/RuleOfTwo.cpp b/cpp/ql/src/Best Practices/RuleOfTwo.cpp index 4e602c10543..d633f9db980 100644 --- a/cpp/ql/src/Best Practices/RuleOfTwo.cpp +++ b/cpp/ql/src/Best Practices/RuleOfTwo.cpp @@ -1,26 +1,26 @@ -class C { -private: - Other* other = NULL; -public: - C(const C& copyFrom) { - Other* newOther = new Other(); - *newOther = copyFrom.other; - this->other = newOther; - } - - //No operator=, by default will just copy the pointer other, will not create a new object -}; - -class D { - Other* other = NULL; -public: - D& operator=(D& rhs) { - Other* newOther = new Other(); - *newOther = rhs.other; - this->other = newOther; - return *this; - } - - //No copy constructor, will just copy the pointer other and not create a new object -}; - +class C { +private: + Other* other = NULL; +public: + C(const C& copyFrom) { + Other* newOther = new Other(); + *newOther = copyFrom.other; + this->other = newOther; + } + + //No operator=, by default will just copy the pointer other, will not create a new object +}; + +class D { + Other* other = NULL; +public: + D& operator=(D& rhs) { + Other* newOther = new Other(); + *newOther = rhs.other; + this->other = newOther; + return *this; + } + + //No copy constructor, will just copy the pointer other and not create a new object +}; + diff --git a/cpp/ql/src/Best Practices/SwitchLongCase.cpp b/cpp/ql/src/Best Practices/SwitchLongCase.cpp index 422c3fdbf56..7b8a0e66808 100644 --- a/cpp/ql/src/Best Practices/SwitchLongCase.cpp +++ b/cpp/ql/src/Best Practices/SwitchLongCase.cpp @@ -1,32 +1,32 @@ -//This switch statement has long case statements, and can become difficult to -//read as the processing for each message type becomes more complex -switch (message_type) { - case CONNECT: - _state = CONNECTING; - int message_id = message_get_id(message); - int source = connect_get_source(message); - //More code here... - send(connect_response); - break; - case DISCONNECT: - _state = DISCONNECTING; - int message_id = message_get_id(message); - int source = disconnect_get_source(message); - //More code here... - send(disconnect_response); - break; - default: - log("Invalid message, id : %d", message_get_id(message)); -} - -//This is better, as each case is split out to a separate function -switch (packet_type) { - case STREAM: - process_stream_packet(packet); - break; - case DATAGRAM: - process_datagram_packet(packet); - break; - default: - log("Invalid packet type: %d", packet_type); +//This switch statement has long case statements, and can become difficult to +//read as the processing for each message type becomes more complex +switch (message_type) { + case CONNECT: + _state = CONNECTING; + int message_id = message_get_id(message); + int source = connect_get_source(message); + //More code here... + send(connect_response); + break; + case DISCONNECT: + _state = DISCONNECTING; + int message_id = message_get_id(message); + int source = disconnect_get_source(message); + //More code here... + send(disconnect_response); + break; + default: + log("Invalid message, id : %d", message_get_id(message)); +} + +//This is better, as each case is split out to a separate function +switch (packet_type) { + case STREAM: + process_stream_packet(packet); + break; + case DATAGRAM: + process_datagram_packet(packet); + break; + default: + log("Invalid packet type: %d", packet_type); } \ No newline at end of file diff --git a/cpp/ql/src/Best Practices/Unused Entities/UnusedLocals.cpp b/cpp/ql/src/Best Practices/Unused Entities/UnusedLocals.cpp index 0f20fd9d529..277e753b06b 100644 --- a/cpp/ql/src/Best Practices/Unused Entities/UnusedLocals.cpp +++ b/cpp/ql/src/Best Practices/Unused Entities/UnusedLocals.cpp @@ -1,5 +1,5 @@ -{ - int x = 0; //x is unused - int y = 0; - cout << y; -} +{ + int x = 0; //x is unused + int y = 0; + cout << y; +} diff --git a/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticFunctions.cpp b/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticFunctions.cpp index 9e2685ea7c4..a1b259e2c47 100644 --- a/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticFunctions.cpp +++ b/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticFunctions.cpp @@ -1,14 +1,14 @@ -//start of file -static void f() { //static function f() is unused in the file - //... -} -static void g() { - //... -} -void public_func() { //non-static function public_func is not called in file, - //but could be visible in other files - //... - g(); //call to g() - //... -} -//end of file +//start of file +static void f() { //static function f() is unused in the file + //... +} +static void g() { + //... +} +void public_func() { //non-static function public_func is not called in file, + //but could be visible in other files + //... + g(); //call to g() + //... +} +//end of file diff --git a/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.cpp b/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.cpp index 4627aab67b3..c5d92cc6eef 100644 --- a/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.cpp +++ b/cpp/ql/src/Best Practices/Unused Entities/UnusedStaticVariables.cpp @@ -1,5 +1,5 @@ -void f() { - static int i = 0; //i is unused - ... - return; -} +void f() { + static int i = 0; //i is unused + ... + return; +} diff --git a/cpp/ql/src/Critical/DeadCodeCondition.cpp b/cpp/ql/src/Critical/DeadCodeCondition.cpp index 743dc39c1b3..1a0eec18bca 100644 --- a/cpp/ql/src/Critical/DeadCodeCondition.cpp +++ b/cpp/ql/src/Critical/DeadCodeCondition.cpp @@ -1,19 +1,19 @@ -while(result) { - if ( ... ) - ... - else if (result //wrong: this test is redundant - && result->flags != 0) - ... - result = next(queue); -} - - -fp = fopen(log, "r"); -if (fp) { - /* - * large block of code - */ - if (!fp) { //wrong: always false - ... /* dead code */ - } -} +while(result) { + if ( ... ) + ... + else if (result //wrong: this test is redundant + && result->flags != 0) + ... + result = next(queue); +} + + +fp = fopen(log, "r"); +if (fp) { + /* + * large block of code + */ + if (!fp) { //wrong: always false + ... /* dead code */ + } +} diff --git a/cpp/ql/src/Critical/DeadCodeFunction.cpp b/cpp/ql/src/Critical/DeadCodeFunction.cpp index e16dc9c3bf5..1cdcc652d97 100644 --- a/cpp/ql/src/Critical/DeadCodeFunction.cpp +++ b/cpp/ql/src/Critical/DeadCodeFunction.cpp @@ -1,12 +1,12 @@ -class C { -public: - void g() { - ... - //f() was previously used but is now commented, orphaning f() - //f(); - ... - } -private: - void f() { //is now unused, and can be removed - } -}; +class C { +public: + void g() { + ... + //f() was previously used but is now commented, orphaning f() + //f(); + ... + } +private: + void f() { //is now unused, and can be removed + } +}; diff --git a/cpp/ql/src/Critical/DescriptorMayNotBeClosed.cpp b/cpp/ql/src/Critical/DescriptorMayNotBeClosed.cpp index 69b83a9a490..a29e0d634d7 100644 --- a/cpp/ql/src/Critical/DescriptorMayNotBeClosed.cpp +++ b/cpp/ql/src/Critical/DescriptorMayNotBeClosed.cpp @@ -1,9 +1,9 @@ -int f() { - try { - int sockfd = socket(AF_INET, SOCK_STREAM, 0); - do_stuff(sockfd); - return sockfd; //if there are no exceptions, the socket is returned - } catch (int do_stuff_exception) { - return -1; //return error value, but sockfd may still be open - } -} +int f() { + try { + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + do_stuff(sockfd); + return sockfd; //if there are no exceptions, the socket is returned + } catch (int do_stuff_exception) { + return -1; //return error value, but sockfd may still be open + } +} diff --git a/cpp/ql/src/Critical/DescriptorNeverClosed.cpp b/cpp/ql/src/Critical/DescriptorNeverClosed.cpp index d791a7024bf..137e962ac64 100644 --- a/cpp/ql/src/Critical/DescriptorNeverClosed.cpp +++ b/cpp/ql/src/Critical/DescriptorNeverClosed.cpp @@ -1,6 +1,6 @@ -int main(int argc, char* argv[]) { - int sockfd = socket(AF_INET, SOCK_STREAM, 0); - int status = 0; - ... //code that does not close sockfd - return status; //sockfd is never closed -} +int main(int argc, char* argv[]) { + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + int status = 0; + ... //code that does not close sockfd + return status; //sockfd is never closed +} diff --git a/cpp/ql/src/Critical/GlobalUseBeforeInit.cpp b/cpp/ql/src/Critical/GlobalUseBeforeInit.cpp index 30fb4ca1cee..dc3a35c8aae 100644 --- a/cpp/ql/src/Critical/GlobalUseBeforeInit.cpp +++ b/cpp/ql/src/Critical/GlobalUseBeforeInit.cpp @@ -1,11 +1,11 @@ -int g_callCtr; - -void initGlobals() { - g_callCtr = 0; -} - -int main(int argc, char* argv[]) { - ... - cout << g_callCtr; //callCtr used before it is initialized - initGlobals(); -} +int g_callCtr; + +void initGlobals() { + g_callCtr = 0; +} + +int main(int argc, char* argv[]) { + ... + cout << g_callCtr; //callCtr used before it is initialized + initGlobals(); +} diff --git a/cpp/ql/src/Critical/InitialisationNotRun.cpp b/cpp/ql/src/Critical/InitialisationNotRun.cpp index 2c937d4b9b9..ab67945e636 100644 --- a/cpp/ql/src/Critical/InitialisationNotRun.cpp +++ b/cpp/ql/src/Critical/InitialisationNotRun.cpp @@ -1,12 +1,12 @@ -GlobalStorage *g_storage; - -void init() { //initializes g_storage, but is never run from main - g_storage = new GlobalStorage(); - ... -} - -int main(int argc, char *argv[]) { - ... //init not called - strcpy(g_storage->name, argv[1]); // g_storage is used before init() is called - ... -} +GlobalStorage *g_storage; + +void init() { //initializes g_storage, but is never run from main + g_storage = new GlobalStorage(); + ... +} + +int main(int argc, char *argv[]) { + ... //init not called + strcpy(g_storage->name, argv[1]); // g_storage is used before init() is called + ... +} diff --git a/cpp/ql/src/Critical/LargeParameter.cpp b/cpp/ql/src/Critical/LargeParameter.cpp index 5e829636132..64a05b85df9 100644 --- a/cpp/ql/src/Critical/LargeParameter.cpp +++ b/cpp/ql/src/Critical/LargeParameter.cpp @@ -1,13 +1,13 @@ -typedef struct Names { - char first[100]; - char last[100]; -} Names; - -int doFoo(Names n) { //wrong: n is passed by value (meaning the entire structure - //is copied onto the stack, instead of just a pointer) - ... -} - -int doBar(Names &n) { //better, only a reference is passed - ... -} +typedef struct Names { + char first[100]; + char last[100]; +} Names; + +int doFoo(Names n) { //wrong: n is passed by value (meaning the entire structure + //is copied onto the stack, instead of just a pointer) + ... +} + +int doBar(Names &n) { //better, only a reference is passed + ... +} diff --git a/cpp/ql/src/Critical/MissingNullTest.cpp b/cpp/ql/src/Critical/MissingNullTest.cpp index 074f9d285e9..05f2ba2278a 100644 --- a/cpp/ql/src/Critical/MissingNullTest.cpp +++ b/cpp/ql/src/Critical/MissingNullTest.cpp @@ -1,11 +1,11 @@ -typedef struct { - char name[100]; - int status; -} person; - -void f() { - person* buf = NULL; - buf = malloc(sizeof(person)); - - (*buf).status = 0; //access to buf before it was checked for NULL -} +typedef struct { + char name[100]; + int status; +} person; + +void f() { + person* buf = NULL; + buf = malloc(sizeof(person)); + + (*buf).status = 0; //access to buf before it was checked for NULL +} diff --git a/cpp/ql/src/Critical/NewArrayDeleteMismatch.cpp b/cpp/ql/src/Critical/NewArrayDeleteMismatch.cpp index 2ee7ed26732..94265b6262b 100644 --- a/cpp/ql/src/Critical/NewArrayDeleteMismatch.cpp +++ b/cpp/ql/src/Critical/NewArrayDeleteMismatch.cpp @@ -1,5 +1,5 @@ -Record* record = new Record[SIZE]; - -... - -delete record; //record was created using 'new[]', but was freed using 'delete' +Record* record = new Record[SIZE]; + +... + +delete record; //record was created using 'new[]', but was freed using 'delete' diff --git a/cpp/ql/src/Critical/NewDeleteArrayMismatch.cpp b/cpp/ql/src/Critical/NewDeleteArrayMismatch.cpp index 31aaa24a832..4ee57b7e20e 100644 --- a/cpp/ql/src/Critical/NewDeleteArrayMismatch.cpp +++ b/cpp/ql/src/Critical/NewDeleteArrayMismatch.cpp @@ -1,5 +1,5 @@ -Record *ptr = new Record(...); - -... - -delete [] ptr; // ptr was created using 'new', but was freed using 'delete[]' +Record *ptr = new Record(...); + +... + +delete [] ptr; // ptr was created using 'new', but was freed using 'delete[]' diff --git a/cpp/ql/src/Critical/NewFreeMismatch.cpp b/cpp/ql/src/Critical/NewFreeMismatch.cpp index 4a359c0ffa5..14ae95415de 100644 --- a/cpp/ql/src/Critical/NewFreeMismatch.cpp +++ b/cpp/ql/src/Critical/NewFreeMismatch.cpp @@ -1,5 +1,5 @@ -Record *ptr = new Record(...); - -... - -free(ptr); // BAD: ptr was created using 'new', but is being freed using 'free' +Record *ptr = new Record(...); + +... + +free(ptr); // BAD: ptr was created using 'new', but is being freed using 'free' diff --git a/cpp/ql/src/Critical/NotInitialised.cpp b/cpp/ql/src/Critical/NotInitialised.cpp index 7d0e6b8f9be..af9b733e962 100644 --- a/cpp/ql/src/Critical/NotInitialised.cpp +++ b/cpp/ql/src/Critical/NotInitialised.cpp @@ -1,6 +1,6 @@ -{ - int i; - - ... - int g = COEFF * i; //i is used before it is initialized -} +{ + int i; + + ... + int g = COEFF * i; //i is used before it is initialized +} diff --git a/cpp/ql/src/Critical/OverflowDestination.cpp b/cpp/ql/src/Critical/OverflowDestination.cpp index d6413231bbf..1a758430bf4 100644 --- a/cpp/ql/src/Critical/OverflowDestination.cpp +++ b/cpp/ql/src/Critical/OverflowDestination.cpp @@ -1,13 +1,13 @@ - -int main(int argc, char* argv[]) { - char param[SIZE]; - - char arg1[10]; - char arg2[20]; - - //wrong: only uses the size of the source (argv[1]) when using strncpy - strncpy(param, argv[1], strlen(arg1)); - - //correct: uses the size of the destination array as well - strncpy(param, argv[1], min(strlen(arg1, sizeof(param) -1))); -} + +int main(int argc, char* argv[]) { + char param[SIZE]; + + char arg1[10]; + char arg2[20]; + + //wrong: only uses the size of the source (argv[1]) when using strncpy + strncpy(param, argv[1], strlen(arg1)); + + //correct: uses the size of the destination array as well + strncpy(param, argv[1], min(strlen(arg1, sizeof(param) -1))); +} diff --git a/cpp/ql/src/Critical/ReturnValueIgnored.cpp b/cpp/ql/src/Critical/ReturnValueIgnored.cpp index d68d5021bba..5e11e765eb0 100644 --- a/cpp/ql/src/Critical/ReturnValueIgnored.cpp +++ b/cpp/ql/src/Critical/ReturnValueIgnored.cpp @@ -1,23 +1,23 @@ -int doFoo() { - ... - return status; -} - -void f() { - if (doFoo() == OK) { - ... - } -} - -void g() { - int status = doFoo(); - if (status == OK) { - ... - } -} - -void err() { - doFoo(); //doFoo is called but its return value is not checked, and - //the value is checked in other locations - ... -} +int doFoo() { + ... + return status; +} + +void f() { + if (doFoo() == OK) { + ... + } +} + +void g() { + int status = doFoo(); + if (status == OK) { + ... + } +} + +void err() { + doFoo(); //doFoo is called but its return value is not checked, and + //the value is checked in other locations + ... +} diff --git a/cpp/ql/src/Critical/SizeCheck.cpp b/cpp/ql/src/Critical/SizeCheck.cpp index 6400e9d4fb5..5f3ec91ad1e 100644 --- a/cpp/ql/src/Critical/SizeCheck.cpp +++ b/cpp/ql/src/Critical/SizeCheck.cpp @@ -1,10 +1,10 @@ -#define RECORD_SIZE 30 //incorrect or outdated size for record -typedef struct { - char name[30]; - int status; -} Record; - -void f() { - Record* p = malloc(RECORD_SIZE); //not of sufficient size to hold a Record - ... -} +#define RECORD_SIZE 30 //incorrect or outdated size for record +typedef struct { + char name[30]; + int status; +} Record; + +void f() { + Record* p = malloc(RECORD_SIZE); //not of sufficient size to hold a Record + ... +} diff --git a/cpp/ql/src/Critical/Unused.cpp b/cpp/ql/src/Critical/Unused.cpp index 01c60357397..bda3329d7c0 100644 --- a/cpp/ql/src/Critical/Unused.cpp +++ b/cpp/ql/src/Critical/Unused.cpp @@ -1,4 +1,4 @@ -{ - int foo = 1; - ... //foo is unused -} +{ + int foo = 1; + ... //foo is unused +} diff --git a/cpp/ql/src/Critical/UseAfterFree.cpp b/cpp/ql/src/Critical/UseAfterFree.cpp index 448696b4bb7..da921a6a31a 100644 --- a/cpp/ql/src/Critical/UseAfterFree.cpp +++ b/cpp/ql/src/Critical/UseAfterFree.cpp @@ -1,9 +1,9 @@ -int f() { - char* buf = new char[SIZE]; - .... - if (error) { - free(buf); //error handling has freed the buffer - } - ... - log_contents(buf); //but it is still used here for logging -} +int f() { + char* buf = new char[SIZE]; + .... + if (error) { + free(buf); //error handling has freed the buffer + } + ... + log_contents(buf); //but it is still used here for logging +} diff --git a/cpp/ql/src/Documentation/TodoComments.cpp b/cpp/ql/src/Documentation/TodoComments.cpp index 2404ca2b2e9..15cfb35b4e9 100644 --- a/cpp/ql/src/Documentation/TodoComments.cpp +++ b/cpp/ql/src/Documentation/TodoComments.cpp @@ -1,4 +1,4 @@ -int isOdd(int n) { - //TODO: Works only for positive n. Need to check if negative n is valid input - return (n % 2) == 1; +int isOdd(int n) { + //TODO: Works only for positive n. Need to check if negative n is valid input + return (n % 2) == 1; } \ No newline at end of file diff --git a/cpp/ql/src/Header Cleanup/Cleanup-DuplicateIncludeGuard.cpp b/cpp/ql/src/Header Cleanup/Cleanup-DuplicateIncludeGuard.cpp index 2b4e70c98ab..30904384a3a 100644 --- a/cpp/ql/src/Header Cleanup/Cleanup-DuplicateIncludeGuard.cpp +++ b/cpp/ql/src/Header Cleanup/Cleanup-DuplicateIncludeGuard.cpp @@ -1,8 +1,8 @@ -// header_file.h - -#ifndef HEADER_FILE_H -#define HEADER_FILE_H - - // ... - +// header_file.h + +#ifndef HEADER_FILE_H +#define HEADER_FILE_H + + // ... + #endif // HEADER_FILE_H \ No newline at end of file diff --git a/cpp/ql/src/Header Cleanup/Cleanup-DuplicateIncludeGuard2.cpp b/cpp/ql/src/Header Cleanup/Cleanup-DuplicateIncludeGuard2.cpp index 3a5d7afd9c2..5057800dcf6 100644 --- a/cpp/ql/src/Header Cleanup/Cleanup-DuplicateIncludeGuard2.cpp +++ b/cpp/ql/src/Header Cleanup/Cleanup-DuplicateIncludeGuard2.cpp @@ -1,8 +1,8 @@ -// another_header_file.h - -#ifndef HEADER_FILE_H // should be ANOTHER_HEADER_FILE_H -#define HEADER_FILE_H // should be ANOTHER_HEADER_FILE_H - - // ... - +// another_header_file.h + +#ifndef HEADER_FILE_H // should be ANOTHER_HEADER_FILE_H +#define HEADER_FILE_H // should be ANOTHER_HEADER_FILE_H + + // ... + #endif // HEADER_FILE_H \ No newline at end of file diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.cpp index 07f1a0529e9..34b7239ba41 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/ComparisonPrecedence.cpp @@ -1,6 +1,6 @@ -void h() { - int a, b, c; - - a < b != c; //parenthesize to explicitly define order of operators - (a < b) < c; //correct: parenthesized to specify order -} +void h() { + int a, b, c; + + a < b != c; //parenthesize to explicitly define order of operators + (a < b) < c; //correct: parenthesized to specify order +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql b/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql index ac2bed3d6f9..885039e9d58 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql @@ -21,17 +21,19 @@ import semmle.code.cpp.controlflow.SSA /** * Holds if `e` is either: * - a constant + * - a char-typed expression, meaning it's a small number * - an array access to an array of constants * - flows from one of the above * In these cases the value of `e` is likely to be small and * controlled, so we consider it less likely to cause an overflow. */ -predicate effectivelyConstant(Expr e) { +predicate likelySmall(Expr e) { e.isConstant() or + e.getType().getSize() <= 1 or e.(ArrayExpr).getArrayBase().getType().(ArrayType).getBaseType().isConst() or exists(SsaDefinition def, Variable v | 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 | op = getMulOperand*(me) and not op instanceof MulExpr and - not effectivelyConstant(op) + not likelySmall(op) ) } diff --git a/cpp/ql/src/Likely Bugs/Conversion/ArrayArgSizeMismatch.cpp b/cpp/ql/src/Likely Bugs/Conversion/ArrayArgSizeMismatch.cpp index eff2e167c1d..20c8b031d78 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/ArrayArgSizeMismatch.cpp +++ b/cpp/ql/src/Likely Bugs/Conversion/ArrayArgSizeMismatch.cpp @@ -1,13 +1,13 @@ - -//Function foo's array parameter has a specified size -void foo(int a[10]) { - int i = 0; - for (i = 0; i <10; i++) { - a[i] = i * 2; - } -} - -... - -int my_arr[5]; + +//Function foo's array parameter has a specified size +void foo(int a[10]) { + int i = 0; + for (i = 0; i <10; i++) { + a[i] = i * 2; + } +} + +... + +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 \ No newline at end of file diff --git a/cpp/ql/src/Likely Bugs/Conversion/ConversionChangesSign.cpp b/cpp/ql/src/Likely Bugs/Conversion/ConversionChangesSign.cpp index f2f049de4a7..e19d001dd9f 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/ConversionChangesSign.cpp +++ b/cpp/ql/src/Likely Bugs/Conversion/ConversionChangesSign.cpp @@ -1,4 +1,4 @@ -//sz is a signed integer, but malloc expects one that is unsigned. -//Negative values will be interpreted as a large number, which may -//lead to unexpected behavior -char *buf = malloc(sz); +//sz is a signed integer, but malloc expects one that is unsigned. +//Negative values will be interpreted as a large number, which may +//lead to unexpected behavior +char *buf = malloc(sz); diff --git a/cpp/ql/src/Likely Bugs/Conversion/LossyPointerCast.cpp b/cpp/ql/src/Likely Bugs/Conversion/LossyPointerCast.cpp index 9f9bc1b08a8..a96b399541a 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/LossyPointerCast.cpp +++ b/cpp/ql/src/Likely Bugs/Conversion/LossyPointerCast.cpp @@ -1,5 +1,5 @@ -void f(char *p) { - int my_ptr = p; //Wrong: pointer assigned to int, would be incorrect if sizeof(char*) - //is larger than sizeof(int) - //... -} +void f(char *p) { + int my_ptr = p; //Wrong: pointer assigned to int, would be incorrect if sizeof(char*) + //is larger than sizeof(int) + //... +} diff --git a/cpp/ql/src/Likely Bugs/InconsistentCheckReturnNull.cpp b/cpp/ql/src/Likely Bugs/InconsistentCheckReturnNull.cpp index 69f25116ca1..302822f7437 100644 --- a/cpp/ql/src/Likely Bugs/InconsistentCheckReturnNull.cpp +++ b/cpp/ql/src/Likely Bugs/InconsistentCheckReturnNull.cpp @@ -1,30 +1,30 @@ -struct property { - char *name; - int value; -}; - -struct property * get_property(char *key); -struct property * get_property_default(char *key, int default_value); - -void check_properties() { - // this call will get flagged since most - // calls to get_property handle NULL - struct property *p1 = get_property("time"); - if(p1->value > 600) { - ... - } - - // this call will not get flagged since - // the result of the call is checked for NULL - struct property *p2 = get_property("time"); - if(p2 != NULL && p2->value > 600) { - ... - } - - // this call will not get flagged since calls - // to get_property_default rarely handle NULL - struct property *p3 = get_property_default("time", 50); - if(p3->value > 60) { - ... - } -} +struct property { + char *name; + int value; +}; + +struct property * get_property(char *key); +struct property * get_property_default(char *key, int default_value); + +void check_properties() { + // this call will get flagged since most + // calls to get_property handle NULL + struct property *p1 = get_property("time"); + if(p1->value > 600) { + ... + } + + // this call will not get flagged since + // the result of the call is checked for NULL + struct property *p2 = get_property("time"); + if(p2 != NULL && p2->value > 600) { + ... + } + + // this call will not get flagged since calls + // to get_property_default rarely handle NULL + struct property *p3 = get_property_default("time", 50); + if(p3->value > 60) { + ... + } +} diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/BoolValueInBitOp.cpp b/cpp/ql/src/Likely Bugs/Likely Typos/BoolValueInBitOp.cpp index 6774921fb0c..155bba73e21 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/BoolValueInBitOp.cpp +++ b/cpp/ql/src/Likely Bugs/Likely Typos/BoolValueInBitOp.cpp @@ -1,13 +1,13 @@ -if (!flags & SOME_BIT) { //wrong: '!' has higher precedence than '&', so this - // is bracketed as '(!flags) & SOME_BIT', and does not - // check whether a particular bit is set. - // ... -} - -if ((p != NULL) & p->f()) { //wrong: The use of '&' rather than '&&' will still - // de-reference the pointer even if it is NULL. - // ... -} - -int bits = (s > 8) & 0xff; //wrong: Invalid attempt to get the 8 most significant - // bits of a short. +if (!flags & SOME_BIT) { //wrong: '!' has higher precedence than '&', so this + // is bracketed as '(!flags) & SOME_BIT', and does not + // check whether a particular bit is set. + // ... +} + +if ((p != NULL) & p->f()) { //wrong: The use of '&' rather than '&&' will still + // de-reference the pointer even if it is NULL. + // ... +} + +int bits = (s > 8) & 0xff; //wrong: Invalid attempt to get the 8 most significant + // bits of a short. diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/LogicalExprCouldBeSimplified.cpp b/cpp/ql/src/Likely Bugs/Likely Typos/LogicalExprCouldBeSimplified.cpp index f2de7c43c92..d54ca4adec2 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/LogicalExprCouldBeSimplified.cpp +++ b/cpp/ql/src/Likely Bugs/Likely Typos/LogicalExprCouldBeSimplified.cpp @@ -1,11 +1,11 @@ -if (0 || condition) { //wrong: can be converted to just 'condition' - //... -} - -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 (0 || condition) { //wrong: can be converted to just 'condition' + //... +} + +if (0 && condition) { //wrong: always evaluates to false, if statement can be removed + // ... +} + +if ('A' == 65 && condition) { // wrong: can be converted to just 'condition' + // ... +} diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.cpp b/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.cpp index cec5e9337e8..11eb9de130e 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.cpp +++ b/cpp/ql/src/Likely Bugs/Likely Typos/MissingEnumCaseInSwitch.cpp @@ -1,30 +1,30 @@ -typedef enum { - RED, - ORANGE, - YELLOW, - GREEN, - BLUE, - INDIGO, - VIOLET -} colors; - -int f(colors c) { - switch (c) { - case RED: - //... - case GREEN: - //... - case BLUE: - //... - //wrong: does not use all enum values, and has no default - } - - switch(c) { - case RED: - //... - case GREEN: - //... - default: - //correct: does not use all enum values, but has a default - } -} +typedef enum { + RED, + ORANGE, + YELLOW, + GREEN, + BLUE, + INDIGO, + VIOLET +} colors; + +int f(colors c) { + switch (c) { + case RED: + //... + case GREEN: + //... + case BLUE: + //... + //wrong: does not use all enum values, and has no default + } + + switch(c) { + case RED: + //... + case GREEN: + //... + default: + //correct: does not use all enum values, but has a default + } +} diff --git a/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.cpp b/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.cpp index efb2569797c..cf83c251efc 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.cpp +++ b/cpp/ql/src/Likely Bugs/Memory Management/PotentialBufferOverflow.cpp @@ -1,12 +1,12 @@ -void f(char* s, float f) { - char buf[30]; - - //wrong: gets has no limit to the length of data it puts in the buffer - gets(buf); - - //wrong: sprintf does not limit the length of the string put into buf - sprintf(buf, "This is a string: %s", s); - - //wrong: %f can expand to a very long string in extreme cases, easily overrunning this buffer - sprintf(buf, "This is a float: %f", f); -} +void f(char* s, float f) { + char buf[30]; + + //wrong: gets has no limit to the length of data it puts in the buffer + gets(buf); + + //wrong: sprintf does not limit the length of the string put into buf + sprintf(buf, "This is a string: %s", s); + + //wrong: %f can expand to a very long string in extreme cases, easily overrunning this buffer + sprintf(buf, "This is a float: %f", f); +} diff --git a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.cpp b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.cpp index 219d082414d..c5cbcd2d7f1 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.cpp +++ b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.cpp @@ -1,4 +1,4 @@ -strncat(dest, src, strlen(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. +strncat(dest, src, strlen(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. diff --git a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousSizeof.cpp b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousSizeof.cpp index 7c38d27a73a..ba76ea2dad7 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousSizeof.cpp +++ b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousSizeof.cpp @@ -1,4 +1,4 @@ -void f(char s[]) { - int size = sizeof(s); //wrong: s is now a char*, not an array. - //sizeof(s) will evaluate to sizeof(char *) -} +void f(char s[]) { + int size = sizeof(s); //wrong: s is now a char*, not an array. + //sizeof(s) will evaluate to sizeof(char *) +} diff --git a/cpp/ql/src/Likely Bugs/NestedLoopSameVar.cpp b/cpp/ql/src/Likely Bugs/NestedLoopSameVar.cpp index 7dd968cec7d..96aed351778 100644 --- a/cpp/ql/src/Likely Bugs/NestedLoopSameVar.cpp +++ b/cpp/ql/src/Likely Bugs/NestedLoopSameVar.cpp @@ -1,16 +1,16 @@ -int x1 = 0; -for (x1 = 0; x1 < 100; x1++) { - int x2 = 0; - for (x1 = 0; x1 < 300; x1++) { - // this is most likely a typo - // the outer loop will exit immediately - } -} - -for (x1 = 0; x1 < 100; x1++) { - if(x1 == 10 && condition) { - for (; x1 < 75; x1++) { - // this should be written as a while loop - } - } -} +int x1 = 0; +for (x1 = 0; x1 < 100; x1++) { + int x2 = 0; + for (x1 = 0; x1 < 300; x1++) { + // this is most likely a typo + // the outer loop will exit immediately + } +} + +for (x1 = 0; x1 < 100; x1++) { + if(x1 == 10 && condition) { + for (; x1 < 75; x1++) { + // this should be written as a while loop + } + } +} diff --git a/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.cpp b/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.cpp index 93ceb8dd111..cc9fae1221f 100644 --- a/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.cpp +++ b/cpp/ql/src/Likely Bugs/OO/NonVirtualDestructor.cpp @@ -1,31 +1,31 @@ -class Base { -public: - Resource *p; - Base() { - p = createResource(); - } - //... - ~Base() { - //wrong: this destructor is non-virtual, but Base has a derived class - // with a non-virtual destructor - freeResource(p); - } -}; - -class Derived: public Base { -public: - Resource *dp; - Derived() { - dp = createResource2(); - } - ~Derived() { - freeResource2(dp); - } -}; - -int f() { - Base *b = new Derived(); //creates resources for both Base::p and Derived::dp - //... - delete b; //will only call Base::~Base(), leaking the resource dp. - // Change both destructors to virtual to ensure they are both called. -} +class Base { +public: + Resource *p; + Base() { + p = createResource(); + } + //... + ~Base() { + //wrong: this destructor is non-virtual, but Base has a derived class + // with a non-virtual destructor + freeResource(p); + } +}; + +class Derived: public Base { +public: + Resource *dp; + Derived() { + dp = createResource2(); + } + ~Derived() { + freeResource2(dp); + } +}; + +int f() { + Base *b = new Derived(); //creates resources for both Base::p and Derived::dp + //... + delete b; //will only call Base::~Base(), leaking the resource dp. + // Change both destructors to virtual to ensure they are both called. +} diff --git a/cpp/ql/src/Likely Bugs/OO/ThrowInDestructor.cpp b/cpp/ql/src/Likely Bugs/OO/ThrowInDestructor.cpp index 77f95e0b257..d7dcbec116a 100644 --- a/cpp/ql/src/Likely Bugs/OO/ThrowInDestructor.cpp +++ b/cpp/ql/src/Likely Bugs/OO/ThrowInDestructor.cpp @@ -1,19 +1,19 @@ -class C { -public: - //... - ~C(){ - if (error) { - throw "Exception in destructor"; //wrong: exception thrown in destructor - } - } -}; - -void f() { - C* c = new C(); - try { - doOperation(c); - delete c; - } catch ( char * do_operation_exception) { - delete c; //would immediately terminate program if C::~C throws an exception - } -} +class C { +public: + //... + ~C(){ + if (error) { + throw "Exception in destructor"; //wrong: exception thrown in destructor + } + } +}; + +void f() { + C* c = new C(); + try { + doOperation(c); + delete c; + } catch ( char * do_operation_exception) { + delete c; //would immediately terminate program if C::~C throws an exception + } +} diff --git a/cpp/ql/src/Likely Bugs/ShortLoopVarName.cpp b/cpp/ql/src/Likely Bugs/ShortLoopVarName.cpp index 568c994ec64..c1d299c231f 100644 --- a/cpp/ql/src/Likely Bugs/ShortLoopVarName.cpp +++ b/cpp/ql/src/Likely Bugs/ShortLoopVarName.cpp @@ -1,14 +1,14 @@ -int i = 0; -for (i = 0; i < NUM_RECORDS; i++) { - int j = 0; - //This loop should have a more descriptive iteration variable - for (j = 0; j < NUM_FIELDS; j++) { - process(record[i]->field[j]); - } - - int field_idx = 0; - //Better: the inner loop has a descriptive name - for (field_idx = 0; field_idx < NUM_FIELDS; field_idx++) { - save(record[i]->field[field_idx]); - } +int i = 0; +for (i = 0; i < NUM_RECORDS; i++) { + int j = 0; + //This loop should have a more descriptive iteration variable + for (j = 0; j < NUM_FIELDS; j++) { + process(record[i]->field[j]); + } + + int field_idx = 0; + //Better: the inner loop has a descriptive name + for (field_idx = 0; field_idx < NUM_FIELDS; field_idx++) { + save(record[i]->field[field_idx]); + } } \ No newline at end of file diff --git a/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.c b/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.c index 4f3b0dd2cf4..62acb4d15e5 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.c +++ b/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.c @@ -1,28 +1,28 @@ -void main(int argc, char **argv) { - uint32_t big_num = INT32_MAX; - char buf[big_num]; - int16_t bytes_received = 0; - int max_get = INT16_MAX + 1; - - // BAD: 'bytes_received' is compared with a value of a wider type. - // 'bytes_received' overflows before reaching 'max_get', - // causing an infinite loop - while (bytes_received < max_get) - bytes_received += get_from_input(buf, bytes_received); - } - - uint32_t bytes_received = 0; - - // GOOD: 'bytes_received2' has a type at least as wide as 'max_get' - while (bytes_received < max_get) { - bytes_received += get_from_input(buf, bytes_received); - } - -} - - -int getFromInput(char *buf, short pos) { - // write to buf - // ... - return 1; -} +void main(int argc, char **argv) { + uint32_t big_num = INT32_MAX; + char buf[big_num]; + int16_t bytes_received = 0; + int max_get = INT16_MAX + 1; + + // BAD: 'bytes_received' is compared with a value of a wider type. + // 'bytes_received' overflows before reaching 'max_get', + // causing an infinite loop + while (bytes_received < max_get) + bytes_received += get_from_input(buf, bytes_received); + } + + uint32_t bytes_received = 0; + + // GOOD: 'bytes_received2' has a type at least as wide as 'max_get' + while (bytes_received < max_get) { + bytes_received += get_from_input(buf, bytes_received); + } + +} + + +int getFromInput(char *buf, short pos) { + // write to buf + // ... + return 1; +} diff --git a/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.cpp b/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.cpp new file mode 100644 index 00000000000..44896e89e15 --- /dev/null +++ b/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.cpp @@ -0,0 +1,7 @@ +LPMALLOC pMalloc; +HRESULT hr = CoGetMalloc(1, &pMalloc); + +if (!hr) +{ + // code ... +} diff --git a/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.qhelp b/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.qhelp new file mode 100644 index 00000000000..d5b949691f0 --- /dev/null +++ b/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.qhelp @@ -0,0 +1,26 @@ + + + + +

This query indicates that an HRESULT is being cast to a boolean type or vice versa.

+

The typical success value (S_OK) of an HRESULT equals 0. However, 0 indicates failure for a boolean type.

+

Casting an HRESULT to a boolean type and then using it in a test expression will yield an incorrect result.

+
+ + +

To check if a call that returns an HRESULT succeeded use the FAILED macro.

+
+ + +

In the following example, HRESULT is used in a test expression incorrectly as it may yield an incorrect result.

+ + +

To fix this issue, use the FAILED macro in the test expression.

+
+ + + + +
diff --git a/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql b/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql new file mode 100644 index 00000000000..7678cff23f0 --- /dev/null +++ b/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql @@ -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 \ No newline at end of file diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql index 22ee7204b91..853285050a4 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql @@ -10,33 +10,69 @@ * external/cwe/cwe-404 */ 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 -// will only apply if the resource is the *return value* of the -// first call and a *parameter* to the second. Other cases should -// be handled differently. -predicate resourceManagementPair(string acquire, string release) { - - (acquire = "fopen" and release = "fclose") - or - (acquire = "open" and release = "close") - or - (acquire = "socket" and release = "close") - +/** + * An expression that acquires a resource, and the kind of resource that is acquired. The + * kind of a resource indicates which acquisition/release expressions can be paired. + */ +predicate acquireExpr(Expr acquire, string kind) { + exists(FunctionCall fc, Function f, string name | + fc = acquire and + f = fc.getTarget() and + name = f.getName() and + ( + ( + 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 -predicate mallocFunction(Function malloc) { - malloc.hasName("malloc") or malloc.hasName("calloc") or // Not realloc: doesn't acquire it, really - malloc.hasName("strdup") -} - -private predicate isRelease(string release) { - resourceManagementPair(_, release) or - release = "free" or - release = "delete" +/** + * An expression that releases a resource, and the kind of resource that is released. The + * kind of a resource indicates which acquisition/release expressions can be paired. + */ +predicate releaseExpr(Expr release, Expr resource, string kind) { + exists(FunctionCall fc, Function f, string name | + fc = release and + f = fc.getTarget() and + name = f.getName() and + ( + ( + 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 * 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.(FunctionCall).getTarget().getName() = releaseType and - 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" + // `e` is a call to a release function and `released` is the released argument + releaseExpr(e, released, kind) ) or exists(Function f, int arg | // `e` is a call to a function that releases one of it's parameters, // and `released` is the corresponding argument e.(FunctionCall).getTarget() = f and e.(FunctionCall).getArgument(arg) = released and - exprReleases(_, exprOrDereference(f.getParameter(arg).getAnAccess()), releaseType) - ) or exists(Function f, Expr innerThis | + exprReleases(_, exprOrDereference(f.getParameter(arg).getAnAccess()), kind) + ) or exists(Function f, ThisExpr innerThis | // `e` is a call to a method that releases `this`, and `released` // is the object that is called e.(FunctionCall).getTarget() = f and e.(FunctionCall).getQualifier() = exprOrDereference(released) and innerThis.getEnclosingFunction() = f and - exprReleases(_, innerThis, releaseType) and - innerThis instanceof ThisExpr and - releaseType = "delete" + exprReleases(_, innerThis, kind) ) } @@ -109,28 +133,17 @@ class Resource extends MemberVariable { ) } - predicate acquisitionWithRequiredRelease(Expr acquire, string releaseName) { - acquire.(Assignment).getLValue() = this.getAnAccess() and + predicate acquisitionWithRequiredRelease(Assignment acquireAssign, string kind) { + // acquireAssign is an assignment to this resource + acquireAssign.(Assignment).getLValue() = this.getAnAccess() and // 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 - ( - 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") - ) + acquireExpr(acquireAssign.getRValue(), kind) } - private Assignment getANew() { - result.getLValue() = this.getAnAccess() and - (result.getRValue() instanceof NewExpr or result.getRValue() instanceof NewArrayExpr) and - this.inSameClass(result) - } - - Expr getAReleaseExpr(string releaseName) { - exprReleases(result, this.getAnAccess(), releaseName) + Expr getAReleaseExpr(string kind) { + exprReleases(result, this.getAnAccess(), kind) } } diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 95.cpp b/cpp/ql/src/jsf/4.10 Classes/AV Rule 95.cpp index 2c9a76e676e..3ae1ca4db66 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 95.cpp +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 95.cpp @@ -1,20 +1,20 @@ -enum Shape_color { red, green, blue }; -class Shape -{ - public: - virtual void draw (Shape_color color = green) const; - ... -} -class Circle : public Shape -{ - public: - virtual void draw (Shape_color color = red) const; - ... -} -void fun() -{ - Shape* sp; - - sp = new Circle; - sp->draw (); // Invokes Circle::draw(green) even though the default -} // parameter for Circle is red. +enum Shape_color { red, green, blue }; +class Shape +{ + public: + virtual void draw (Shape_color color = green) const; + ... +} +class Circle : public Shape +{ + public: + virtual void draw (Shape_color color = red) const; + ... +} +void fun() +{ + Shape* sp; + + sp = new Circle; + sp->draw (); // Invokes Circle::draw(green) even though the default +} // parameter for Circle is red. diff --git a/cpp/ql/src/plugin.xml b/cpp/ql/src/plugin.xml index e08a29947a6..d7036c7c347 100644 --- a/cpp/ql/src/plugin.xml +++ b/cpp/ql/src/plugin.xml @@ -1,16 +1,16 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/cpp/ql/src/semmle/code/cpp/Parameter.qll b/cpp/ql/src/semmle/code/cpp/Parameter.qll index 971a2f33f61..c6fc33b9355 100644 --- a/cpp/ql/src/semmle/code/cpp/Parameter.qll +++ b/cpp/ql/src/semmle/code/cpp/Parameter.qll @@ -68,10 +68,9 @@ class Parameter extends LocalScopeVariable, @parameter { */ private VariableDeclarationEntry getAnEffectiveDeclarationEntry() { if getFunction().isConstructedFrom(_) - then exists (Parameter prototype - | prototype = result.getVariable() and - prototype.getIndex() = getIndex() and - getFunction().isConstructedFrom(prototype.getFunction())) + then exists (Function prototypeInstantiation + | prototypeInstantiation.getParameter(getIndex()) = result.getVariable() and + getFunction().isConstructedFrom(prototypeInstantiation)) else result = getADeclarationEntry() } diff --git a/cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll b/cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll index 41c50654130..fd38c749dcc 100644 --- a/cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll +++ b/cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll @@ -1,23 +1,31 @@ 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] private predicate existsCompleteWithName(string name, @usertype d) { - isClass(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`. */ pragma[noinline] private predicate existsIncompleteWithName(string name, @usertype c) { - isClass(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. */ private predicate hasCompleteTwin(@usertype c, @usertype d) { @@ -30,10 +38,8 @@ private predicate hasCompleteTwin(@usertype c, @usertype d) { import Cached cached private module Cached { /** - * If `c` is incomplete, and there exists a complete class with the same name, - * then the result is that complete class. Otherwise, the result is `c`. If - * multiple complete classes have the same name, this predicate may have - * multiple results. + * 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`. */ cached @usertype resolveClass(@usertype c) { hasCompleteTwin(c, result) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 380efb6e924..580dbe0f725 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -270,7 +270,7 @@ newtype TTranslatedElement = not ignoreExpr(initList) and isFirstValueInitializedElementInRange(initList, elementIndex) and elementCount = - getNextExplicitlyInitializedElementAfter(initList, elementIndex) - + getEndOfValueInitializedRange(initList, elementIndex) - elementIndex } or // 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` - * whose index is greater than `afterElementIndex`. If there are no remaining - * explicitly initialized elements in `initList`, the result is the total number - * of elements in the array being initialized. + * whose index is greater than `afterElementIndex`, where `afterElementIndex` + * is a first value-initialized element in a value-initialized range in + * `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( - ArrayAggregateLiteral initList, int afterElementIndex) { - if exists(int x | - x > afterElementIndex and - exists(initList.getElementExpr(x))) - then ( - if exists(initList.getElementExpr(afterElementIndex + 1)) - then result = afterElementIndex + 1 - else result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex+1)) - else - result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize() and - // required for binding - initList.isInitialized(afterElementIndex) +private int getEndOfValueInitializedRange(ArrayAggregateLiteral initList, int afterElementIndex) { + result = getNextExplicitlyInitializedElementAfter(initList, afterElementIndex) + or + isFirstValueInitializedElementInRange(initList, afterElementIndex) and + not exists(getNextExplicitlyInitializedElementAfter(initList, afterElementIndex)) and + result = initList.getType().getUnspecifiedType().(ArrayType).getArraySize() +} + +/** + * Gets the index of the first explicitly initialized element in `initList` + * whose index is greater than `afterElementIndex`, where `afterElementIndex` + * is a first value-initialized element in a value-initialized range in + * `initList`. + */ +private int getNextExplicitlyInitializedElementAfter( + ArrayAggregateLiteral initList, int afterElementIndex) { + isFirstValueInitializedElementInRange(initList, afterElementIndex) and + result = min(int i | exists(initList.getElementExpr(i)) and i > afterElementIndex) } /** diff --git a/cpp/ql/src/tools/instantiate_templates.py b/cpp/ql/src/tools/instantiate_templates.py index 0beeeed20d8..d549a85f82d 100644 --- a/cpp/ql/src/tools/instantiate_templates.py +++ b/cpp/ql/src/tools/instantiate_templates.py @@ -1,137 +1,137 @@ -import sys -import os.path -import glob -import re -import json - -BEGIN_TEMPLATE = re.compile(r"^/\*template\s*$") -END_TEMPLATE = re.compile(r"^\*/\s*$") - -def expand_template_params(args, param_arg_map): - '''Given a list of template arguments that may reference template parameters - of the current template, return a new list of template arguments with each - parameter use replaced with the appropriate fully-qualified argument for - that parameter.''' - result = [] - for arg in args: - if arg in param_arg_map: - result.append(param_arg_map[arg]) - else: - result.append(arg) - - return result - -def find_instantiation(module, args, templates): - '''Given a template module and a set of template arguments, find the module - name of the instantiation of that module with those arguments.''' - template = templates[module] - for instantiation in template["template_def"]["instantiations"]: - if instantiation["args"] == args: - return instantiation["name"] - return None - -def instantiate_template(template, instantiation, root, templates): - '''Create a single instantiation of a template.''' - template_def = template["template_def"] - output_components = instantiation["name"].split(".") - output_path = root - for component in output_components: - output_path = os.path.join(output_path, component) - output_path = output_path + ".qll" - with open(output_path, "w") as output: - output.write( -""" -/* - * THIS FILE IS AUTOMATICALLY GENERATED FROM '%s'. - * DO NOT EDIT MANUALLY. - */ - -""" % (template["name"].replace(".", "/") + ".qllt") - ) - param_arg_map = {} - for param_index in range(len(template_def["params"])): - param = template_def["params"][param_index] - arg = instantiation["args"][param_index] - output.write("private import %s as %s // Template parameter\n" % (arg, param)) - param_arg_map[param] = arg - for import_record in template_def["imports"]: - if "access" in import_record: - output.write(import_record["access"] + " ") - imported_module = find_instantiation(import_record["module"], - expand_template_params(import_record["args"], param_arg_map), templates) - output.write("import %s // %s<%s>\n" % - ( - imported_module, - import_record["module"], - ", ".join(import_record["args"]) - ) - ) - - output.writelines(template_def["body_lines"]) - -def generate_instantiations(template, root, templates): - '''Create a .qll source file for each instantiation of the specified template.''' - template_def = template["template_def"] - if "instantiations" in template_def: - for instantiation in template_def["instantiations"]: - instantiate_template(template, instantiation, root, templates) - -def read_template(template_path, module_name): - '''Read a .qllt template file from template_path, using module_name as the - fully qualified name of the module.''' - with open(template_path) as input: - in_template = False - template_text = "" - template_def = None - body_lines = [] - for line in iter(input): - if in_template: - if END_TEMPLATE.match(line): - template_def = json.loads(template_text) - in_template = False - else: - template_text += line - else: - if BEGIN_TEMPLATE.match(line) and not template_def: - in_template = True - else: - body_lines.append(line) - - if template_def: - template_def["body_lines"] = body_lines - - result = { "name": module_name } - if template_def: - result["template_def"] = template_def - return result - -def module_name_from_path_impl(path): - (head, tail) = os.path.split(path) - if head == "": - return tail - else: - return module_name_from_path(head) + "." + tail - -def module_name_from_path(path): - '''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.''' - (module_root, ext) = os.path.splitext(path) - return module_name_from_path_impl(module_root) - -def main(): - templates = {} - - root = sys.argv[1] - for template_path in glob.glob(os.path.join(root, "**\\*.qllt"), recursive = True): - print(template_path) - module_name = module_name_from_path(os.path.relpath(template_path, root)) - print(module_name) - template = read_template(template_path, module_name) - templates[template["name"]] = template - - for name, template in templates.items(): - if "template_def" in template: - generate_instantiations(template, root, templates) - -if __name__ == "__main__": - main() +import sys +import os.path +import glob +import re +import json + +BEGIN_TEMPLATE = re.compile(r"^/\*template\s*$") +END_TEMPLATE = re.compile(r"^\*/\s*$") + +def expand_template_params(args, param_arg_map): + '''Given a list of template arguments that may reference template parameters + of the current template, return a new list of template arguments with each + parameter use replaced with the appropriate fully-qualified argument for + that parameter.''' + result = [] + for arg in args: + if arg in param_arg_map: + result.append(param_arg_map[arg]) + else: + result.append(arg) + + return result + +def find_instantiation(module, args, templates): + '''Given a template module and a set of template arguments, find the module + name of the instantiation of that module with those arguments.''' + template = templates[module] + for instantiation in template["template_def"]["instantiations"]: + if instantiation["args"] == args: + return instantiation["name"] + return None + +def instantiate_template(template, instantiation, root, templates): + '''Create a single instantiation of a template.''' + template_def = template["template_def"] + output_components = instantiation["name"].split(".") + output_path = root + for component in output_components: + output_path = os.path.join(output_path, component) + output_path = output_path + ".qll" + with open(output_path, "w") as output: + output.write( +""" +/* + * THIS FILE IS AUTOMATICALLY GENERATED FROM '%s'. + * DO NOT EDIT MANUALLY. + */ + +""" % (template["name"].replace(".", "/") + ".qllt") + ) + param_arg_map = {} + for param_index in range(len(template_def["params"])): + param = template_def["params"][param_index] + arg = instantiation["args"][param_index] + output.write("private import %s as %s // Template parameter\n" % (arg, param)) + param_arg_map[param] = arg + for import_record in template_def["imports"]: + if "access" in import_record: + output.write(import_record["access"] + " ") + imported_module = find_instantiation(import_record["module"], + expand_template_params(import_record["args"], param_arg_map), templates) + output.write("import %s // %s<%s>\n" % + ( + imported_module, + import_record["module"], + ", ".join(import_record["args"]) + ) + ) + + output.writelines(template_def["body_lines"]) + +def generate_instantiations(template, root, templates): + '''Create a .qll source file for each instantiation of the specified template.''' + template_def = template["template_def"] + if "instantiations" in template_def: + for instantiation in template_def["instantiations"]: + instantiate_template(template, instantiation, root, templates) + +def read_template(template_path, module_name): + '''Read a .qllt template file from template_path, using module_name as the + fully qualified name of the module.''' + with open(template_path) as input: + in_template = False + template_text = "" + template_def = None + body_lines = [] + for line in iter(input): + if in_template: + if END_TEMPLATE.match(line): + template_def = json.loads(template_text) + in_template = False + else: + template_text += line + else: + if BEGIN_TEMPLATE.match(line) and not template_def: + in_template = True + else: + body_lines.append(line) + + if template_def: + template_def["body_lines"] = body_lines + + result = { "name": module_name } + if template_def: + result["template_def"] = template_def + return result + +def module_name_from_path_impl(path): + (head, tail) = os.path.split(path) + if head == "": + return tail + else: + return module_name_from_path(head) + "." + tail + +def module_name_from_path(path): + '''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.''' + (module_root, ext) = os.path.splitext(path) + return module_name_from_path_impl(module_root) + +def main(): + templates = {} + + root = sys.argv[1] + for template_path in glob.glob(os.path.join(root, "**\\*.qllt"), recursive = True): + print(template_path) + module_name = module_name_from_path(os.path.relpath(template_path, root)) + print(module_name) + template = read_template(template_path, module_name) + templates[template["name"]] = template + + for name, template in templates.items(): + if "template_def" in template: + generate_instantiations(template, root, templates) + +if __name__ == "__main__": + main() diff --git a/cpp/ql/test/.project b/cpp/ql/test/.project index 2dbe9983f8c..bff15d701e3 100644 --- a/cpp/ql/test/.project +++ b/cpp/ql/test/.project @@ -1,12 +1,12 @@ - - - semmlecode-cpp-tests - - - - - - - com.semmle.plugin.qdt.core.qlnature - - + + + semmlecode-cpp-tests + + + + + + + com.semmle.plugin.qdt.core.qlnature + + diff --git a/cpp/ql/test/header-variant-tests/multi-target-includes/common.h b/cpp/ql/test/header-variant-tests/multi-target-includes/common.h index 8c20e36220b..a965769ffd6 100644 --- a/cpp/ql/test/header-variant-tests/multi-target-includes/common.h +++ b/cpp/ql/test/header-variant-tests/multi-target-includes/common.h @@ -1,5 +1,5 @@ -// common.h - -#include "nameclash.h" - +// common.h + +#include "nameclash.h" + static int myArray[sizeof(MYTYPE)]; \ No newline at end of file diff --git a/cpp/ql/test/header-variant-tests/multi-target-includes/defines_issue.h b/cpp/ql/test/header-variant-tests/multi-target-includes/defines_issue.h index f80f739121e..ea10509143e 100644 --- a/cpp/ql/test/header-variant-tests/multi-target-includes/defines_issue.h +++ b/cpp/ql/test/header-variant-tests/multi-target-includes/defines_issue.h @@ -1,3 +1,3 @@ -// defines_issue.h - +// defines_issue.h + #include DEFINED_HEADER \ No newline at end of file diff --git a/cpp/ql/test/header-variant-tests/multi-target-includes/main2.cpp b/cpp/ql/test/header-variant-tests/multi-target-includes/main2.cpp index 49ec6536942..9c4ba0e202c 100644 --- a/cpp/ql/test/header-variant-tests/multi-target-includes/main2.cpp +++ b/cpp/ql/test/header-variant-tests/multi-target-includes/main2.cpp @@ -1,7 +1,7 @@ -// semmle-extractor-options: -I${testdir}/subdir2 -// main2.cpp -#include "common.h" - -#define DEFINED_HEADER "define2.h" - -#include "defines_issue.h" +// semmle-extractor-options: -I${testdir}/subdir2 +// main2.cpp +#include "common.h" + +#define DEFINED_HEADER "define2.h" + +#include "defines_issue.h" diff --git a/cpp/ql/test/header-variant-tests/multi-target-includes/nameclash.h b/cpp/ql/test/header-variant-tests/multi-target-includes/nameclash.h index 9ab85dc2b12..bcfe8abed54 100644 --- a/cpp/ql/test/header-variant-tests/multi-target-includes/nameclash.h +++ b/cpp/ql/test/header-variant-tests/multi-target-includes/nameclash.h @@ -1,3 +1,3 @@ -// nameclash.h - +// nameclash.h + #include_next "nameclash.h" \ No newline at end of file diff --git a/cpp/ql/test/header-variant-tests/multi-target-includes/subdir1/nameclash.h b/cpp/ql/test/header-variant-tests/multi-target-includes/subdir1/nameclash.h index d0361b16bdd..f4a942327c2 100644 --- a/cpp/ql/test/header-variant-tests/multi-target-includes/subdir1/nameclash.h +++ b/cpp/ql/test/header-variant-tests/multi-target-includes/subdir1/nameclash.h @@ -1,3 +1,3 @@ -// subdir1/nameclash.h - +// subdir1/nameclash.h + typedef long long int MYTYPE; \ No newline at end of file diff --git a/cpp/ql/test/header-variant-tests/multi-target-includes/subdir2/nameclash.h b/cpp/ql/test/header-variant-tests/multi-target-includes/subdir2/nameclash.h index 469a0c9b303..0ffbb1fd89b 100644 --- a/cpp/ql/test/header-variant-tests/multi-target-includes/subdir2/nameclash.h +++ b/cpp/ql/test/header-variant-tests/multi-target-includes/subdir2/nameclash.h @@ -1,3 +1,3 @@ -// subdir2/nameclash.h - +// subdir2/nameclash.h + typedef char MYTYPE; \ No newline at end of file diff --git a/cpp/ql/test/library-tests/allocators/allocators.cpp b/cpp/ql/test/library-tests/allocators/allocators.cpp index a32c530f583..5f0a535e7f3 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.cpp +++ b/cpp/ql/test/library-tests/allocators/allocators.cpp @@ -1,111 +1,111 @@ -// semmle-extractor-options: -std=c++17 -typedef unsigned long size_t; -namespace std { - enum class align_val_t : size_t {}; -} - -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 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); - -struct String { - String(); - String(const String&); - String(String&&); - String(const char*); - ~String(); - - String& operator=(const String&); - String& operator=(String&&); - - const char* c_str() const; - -private: - const char* p; -}; - -struct SizedDealloc { - char a[32]; - void* operator new(size_t); - void* operator new[](size_t); - void operator delete(void*, size_t); - void operator delete[](void*, size_t); -}; - -struct alignas(128) Overaligned { - char a[256]; -}; - -struct PolymorphicBase { - virtual ~PolymorphicBase(); -}; - -void OperatorNew() { - new int; // No constructor - new(1.0f) int; // Placement new, no constructor - new int(); // Zero-init - new String(); // Constructor - new(1.0f) String("hello"); // Placement new, constructor with args - new Overaligned; // Aligned new - new(1.0f) Overaligned(); // Placement aligned new -} - -void OperatorDelete() { - delete static_cast(nullptr); // No destructor - delete static_cast(nullptr); // Non-virtual destructor, with size. - delete static_cast(nullptr); // No destructor, with size. - delete static_cast(nullptr); // No destructor, with size and alignment. - delete static_cast(nullptr); // Virtual destructor - delete static_cast(nullptr); // Pointer to const -} - -void OperatorNewArray(int n) { - new int[n]; // No constructor - new(1.0f) int[n]; // Placement new, no constructor - new String[n]; // Constructor - new Overaligned[n]; // Aligned new - new String[10]; // Constant size -} - -int* const GetPointer(); - -void OperatorDeleteArray() { - delete[] static_cast(nullptr); // No destructor - delete[] static_cast(nullptr); // Non-virtual destructor, with size. - delete[] static_cast(nullptr); // No destructor, with size. - delete[] static_cast(nullptr); // No destructor, with size and alignment. - delete[] static_cast(nullptr); // Virtual destructor - delete[] GetPointer(); -} - -struct FailedInit { - FailedInit(); - ~FailedInit(); - - 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 -}; - -struct alignas(128) 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 delete(void*, std::align_val_t, float); // Aligned placement - void operator delete[](void*, std::align_val_t, float); // Aligned placement -}; - -void TestFailedInit(int n) { - new FailedInit(); - new FailedInit[n]; - new(1.0f) FailedInitOveraligned(); - new(1.0f) FailedInitOveraligned[10]; -} +// semmle-extractor-options: -std=c++17 +typedef unsigned long size_t; +namespace std { + enum class align_val_t : size_t {}; +} + +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 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); + +struct String { + String(); + String(const String&); + String(String&&); + String(const char*); + ~String(); + + String& operator=(const String&); + String& operator=(String&&); + + const char* c_str() const; + +private: + const char* p; +}; + +struct SizedDealloc { + char a[32]; + void* operator new(size_t); + void* operator new[](size_t); + void operator delete(void*, size_t); + void operator delete[](void*, size_t); +}; + +struct alignas(128) Overaligned { + char a[256]; +}; + +struct PolymorphicBase { + virtual ~PolymorphicBase(); +}; + +void OperatorNew() { + new int; // No constructor + new(1.0f) int; // Placement new, no constructor + new int(); // Zero-init + new String(); // Constructor + new(1.0f) String("hello"); // Placement new, constructor with args + new Overaligned; // Aligned new + new(1.0f) Overaligned(); // Placement aligned new +} + +void OperatorDelete() { + delete static_cast(nullptr); // No destructor + delete static_cast(nullptr); // Non-virtual destructor, with size. + delete static_cast(nullptr); // No destructor, with size. + delete static_cast(nullptr); // No destructor, with size and alignment. + delete static_cast(nullptr); // Virtual destructor + delete static_cast(nullptr); // Pointer to const +} + +void OperatorNewArray(int n) { + new int[n]; // No constructor + new(1.0f) int[n]; // Placement new, no constructor + new String[n]; // Constructor + new Overaligned[n]; // Aligned new + new String[10]; // Constant size +} + +int* const GetPointer(); + +void OperatorDeleteArray() { + delete[] static_cast(nullptr); // No destructor + delete[] static_cast(nullptr); // Non-virtual destructor, with size. + delete[] static_cast(nullptr); // No destructor, with size. + delete[] static_cast(nullptr); // No destructor, with size and alignment. + delete[] static_cast(nullptr); // Virtual destructor + delete[] GetPointer(); +} + +struct FailedInit { + FailedInit(); + ~FailedInit(); + + 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 +}; + +struct alignas(128) 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 delete(void*, std::align_val_t, float); // Aligned placement + void operator delete[](void*, std::align_val_t, float); // Aligned placement +}; + +void TestFailedInit(int n) { + new FailedInit(); + new FailedInit[n]; + new(1.0f) FailedInitOveraligned(); + new(1.0f) FailedInitOveraligned[10]; +} diff --git a/cpp/ql/test/library-tests/calls/calls1.cpp b/cpp/ql/test/library-tests/calls/calls1.cpp index 0c3f1231227..0b3238b0097 100644 --- a/cpp/ql/test/library-tests/calls/calls1.cpp +++ b/cpp/ql/test/library-tests/calls/calls1.cpp @@ -1,8 +1,8 @@ -#include "calls1.h" - -void swap(int* p, int* q) -{ - int t = *p; - *p = *q; - *q = t; -} +#include "calls1.h" + +void swap(int* p, int* q) +{ + int t = *p; + *p = *q; + *q = t; +} diff --git a/cpp/ql/test/library-tests/calls/calls1.h b/cpp/ql/test/library-tests/calls/calls1.h index 90b150ae9d6..af92b2bded3 100644 --- a/cpp/ql/test/library-tests/calls/calls1.h +++ b/cpp/ql/test/library-tests/calls/calls1.h @@ -1,2 +1,2 @@ - -extern void swap(int*, int*); + +extern void swap(int*, int*); diff --git a/cpp/ql/test/library-tests/calls/calls2.cpp b/cpp/ql/test/library-tests/calls/calls2.cpp index 4f10faa3f20..feedab7f719 100644 --- a/cpp/ql/test/library-tests/calls/calls2.cpp +++ b/cpp/ql/test/library-tests/calls/calls2.cpp @@ -1,20 +1,20 @@ -#include "calls1.h" - -void g() { - int x = 2; - int y = 4; - swap(&x,&y); -} - -void negate(int& c) { c = -c; } - -template void compute(Iter b, Fct f) -{ - f(b); -} - -void f(int aa) -{ - compute(aa, negate); -} - +#include "calls1.h" + +void g() { + int x = 2; + int y = 4; + swap(&x,&y); +} + +void negate(int& c) { c = -c; } + +template void compute(Iter b, Fct f) +{ + f(b); +} + +void f(int aa) +{ + compute(aa, negate); +} + diff --git a/cpp/ql/test/library-tests/classes/classes/Classes.ms.cpp b/cpp/ql/test/library-tests/classes/classes/Classes.ms.cpp index 4dafda9752f..06d239d70cd 100644 --- a/cpp/ql/test/library-tests/classes/classes/Classes.ms.cpp +++ b/cpp/ql/test/library-tests/classes/classes/Classes.ms.cpp @@ -1,41 +1,41 @@ -class A { - -}; - - -class B { - -}; - -class C: A, B { - -}; - -class D: C { - - class E; - -}; - -class D::E { - - class F; - - class G { - public: - /* Non-trivial constructor and destructor */ - G() { 0; } - ~G() { 0; } - }; - -}; - -class D::E::F: D::E::G { - /* Should have generated constructor and destructor, because of D::E::G */ - - static int m() { - D::E::F def; /* Should trigger creation of D::E::F's generated constructor and destructor. */ - } -}; - -// semmle-extractor-options: --microsoft +class A { + +}; + + +class B { + +}; + +class C: A, B { + +}; + +class D: C { + + class E; + +}; + +class D::E { + + class F; + + class G { + public: + /* Non-trivial constructor and destructor */ + G() { 0; } + ~G() { 0; } + }; + +}; + +class D::E::F: D::E::G { + /* Should have generated constructor and destructor, because of D::E::G */ + + static int m() { + D::E::F def; /* Should trigger creation of D::E::F's generated constructor and destructor. */ + } +}; + +// semmle-extractor-options: --microsoft diff --git a/cpp/ql/test/library-tests/classes/derivations/offsets/offsets.cpp b/cpp/ql/test/library-tests/classes/derivations/offsets/offsets.cpp index fed096f45df..745a37ca5c8 100644 --- a/cpp/ql/test/library-tests/classes/derivations/offsets/offsets.cpp +++ b/cpp/ql/test/library-tests/classes/derivations/offsets/offsets.cpp @@ -1,84 +1,84 @@ -struct Base { - int b1; - float b1f; -}; - -struct SingleInheritance : Base { - int si1; - float si1f; -}; - -struct Base2 { - int b2; - float b2f; -}; - -struct MultipleInheritance : Base, Base2 { - int mi1; - float mi1f; -}; - -struct DeepInheritance : MultipleInheritance, SingleInheritance { - int di1; - float di1f; -}; - -struct VirtualInheritance1 : virtual Base { - int vi1; - float vi1f; -}; - -struct VirtualInheritance2 : VirtualInheritance1, virtual Base, virtual Base2 { - int vi2; - float vi2f; -}; - -struct EffectivelyVirtual : virtual SingleInheritance, MultipleInheritance { - int ev1; - float ev1f; -}; - -struct PolymorphicBase { - virtual ~PolymorphicBase(); - int pb1; - float pb1f; -}; - -struct InheritsVTable : PolymorphicBase { - int iv1; - float iv1f; -}; - -struct IntroducesVTable : Base { - virtual ~IntroducesVTable(); - int iv2; - float iv2f; -}; - -struct Left : virtual Base { - int l1; - float l1f; -}; - -struct Right : virtual Base { - int r1; - float r1f; -}; - -struct Bottom : Left, Right { - int b1; - float b1f; -}; - -struct DeepSingleInheritance : SingleInheritance { - int dsi1; - float dsi1f; -}; - -struct Incomplete; -Incomplete* p; - -template -struct TemplateClass : Base -{ -}; +struct Base { + int b1; + float b1f; +}; + +struct SingleInheritance : Base { + int si1; + float si1f; +}; + +struct Base2 { + int b2; + float b2f; +}; + +struct MultipleInheritance : Base, Base2 { + int mi1; + float mi1f; +}; + +struct DeepInheritance : MultipleInheritance, SingleInheritance { + int di1; + float di1f; +}; + +struct VirtualInheritance1 : virtual Base { + int vi1; + float vi1f; +}; + +struct VirtualInheritance2 : VirtualInheritance1, virtual Base, virtual Base2 { + int vi2; + float vi2f; +}; + +struct EffectivelyVirtual : virtual SingleInheritance, MultipleInheritance { + int ev1; + float ev1f; +}; + +struct PolymorphicBase { + virtual ~PolymorphicBase(); + int pb1; + float pb1f; +}; + +struct InheritsVTable : PolymorphicBase { + int iv1; + float iv1f; +}; + +struct IntroducesVTable : Base { + virtual ~IntroducesVTable(); + int iv2; + float iv2f; +}; + +struct Left : virtual Base { + int l1; + float l1f; +}; + +struct Right : virtual Base { + int r1; + float r1f; +}; + +struct Bottom : Left, Right { + int b1; + float b1f; +}; + +struct DeepSingleInheritance : SingleInheritance { + int dsi1; + float dsi1f; +}; + +struct Incomplete; +Incomplete* p; + +template +struct TemplateClass : Base +{ +}; diff --git a/cpp/ql/test/library-tests/controlflow/loopentrycondition/forstmt.cpp b/cpp/ql/test/library-tests/controlflow/loopentrycondition/forstmt.cpp index 8345e3a2da6..f07fec46a58 100644 --- a/cpp/ql/test/library-tests/controlflow/loopentrycondition/forstmt.cpp +++ b/cpp/ql/test/library-tests/controlflow/loopentrycondition/forstmt.cpp @@ -1,102 +1,102 @@ -// GOOD = at least one iteration -// BAD = possibly no iterations - -void test1() { - for (int i = 0; i < 10; i++) { // GOOD - } -} - -void test2() { - for (int i = 0, j = 1; i + j < 10; i++) { // GOOD - } -} - -void test3() { - int j = 2; - for (int i = j = 1; i + j < 10; i++) { // GOOD - } -} - -void test4() { - int i = 2, j = 3; - for (i = j = 1; i + j < 10; i++) { // GOOD - } -} - -void test5() { - int i, k; - for (i = k = 0; i < 10; i++) { // GOOD - } -} - -void test6() { - int i = 0; - for (; i < 10; i++) { // GOOD - i = 1; - } -} - -void test7() { - int i = 0; - for (i = 1; i < 10; i++) { // GOOD - i = 1; - } -} - -void test8() { - int i = 0; - i = 1; - for (; i < 10; i++) { // GOOD (NOT REPORTED) - } -} - -void test9() { - bool done = false; - for (; !done; ) { // GOOD - done = true; - } -} - -void test10(int i) { - bool done = false; - for (; i++; i < 10) { // BAD - for (; !done; ) { // BAD - done = true; - } - } -} - -void test11(int i) { - for (; i++; i < 10) { // BAD - bool done = false; - for (; !done; ) { // GOOD - done = true; - } - } -} - -void test12(int max) { - int i, k; - int max_index = 0; - for (i = k = 0; i < max; i++) { // BAD - max_index = i; - } - for (i = 0; i <= max_index; i++) { // BAD - } -} - -void test13() { - int i; - for (i = 1; i > 0; ) { // GOOD - &i; - } -} - -void test14(bool b) { - int i = 1; - while (b) { - for (; i > 0; ) { // BAD - &i; - } - } +// GOOD = at least one iteration +// BAD = possibly no iterations + +void test1() { + for (int i = 0; i < 10; i++) { // GOOD + } +} + +void test2() { + for (int i = 0, j = 1; i + j < 10; i++) { // GOOD + } +} + +void test3() { + int j = 2; + for (int i = j = 1; i + j < 10; i++) { // GOOD + } +} + +void test4() { + int i = 2, j = 3; + for (i = j = 1; i + j < 10; i++) { // GOOD + } +} + +void test5() { + int i, k; + for (i = k = 0; i < 10; i++) { // GOOD + } +} + +void test6() { + int i = 0; + for (; i < 10; i++) { // GOOD + i = 1; + } +} + +void test7() { + int i = 0; + for (i = 1; i < 10; i++) { // GOOD + i = 1; + } +} + +void test8() { + int i = 0; + i = 1; + for (; i < 10; i++) { // GOOD (NOT REPORTED) + } +} + +void test9() { + bool done = false; + for (; !done; ) { // GOOD + done = true; + } +} + +void test10(int i) { + bool done = false; + for (; i++; i < 10) { // BAD + for (; !done; ) { // BAD + done = true; + } + } +} + +void test11(int i) { + for (; i++; i < 10) { // BAD + bool done = false; + for (; !done; ) { // GOOD + done = true; + } + } +} + +void test12(int max) { + int i, k; + int max_index = 0; + for (i = k = 0; i < max; i++) { // BAD + max_index = i; + } + for (i = 0; i <= max_index; i++) { // BAD + } +} + +void test13() { + int i; + for (i = 1; i > 0; ) { // GOOD + &i; + } +} + +void test14(bool b) { + int i = 1; + while (b) { + for (; i > 0; ) { // BAD + &i; + } + } } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/controlflow/loopentrycondition/whilestmt.cpp b/cpp/ql/test/library-tests/controlflow/loopentrycondition/whilestmt.cpp index e0ddb1b42f1..8155f2fabe9 100644 --- a/cpp/ql/test/library-tests/controlflow/loopentrycondition/whilestmt.cpp +++ b/cpp/ql/test/library-tests/controlflow/loopentrycondition/whilestmt.cpp @@ -1,64 +1,64 @@ -// GOOD = at least one iteration -// BAD = possibly no iterations - -void test1() { - bool done = false; - while (!done) { // GOOD - done = true; - } -} - -void test2() { - bool done = true; - done = false; - while (!done) { // GOOD (NOT REPORTED) - done = true; - } -} - -void test3(int i) { - bool done = false; - for (; i++; i < 10) { - while (!done) { // BAD - done = true; - } - } -} - -void test4(int i) { - for (; i++; i < 10) { - bool done = false; - while (!done) { // GOOD - done = true; - } - } -} - -void test5(int max) { - int i = 0, k = 0; - int max_index = 0; - while (i < max) { // BAD - max_index = i; - i++; - } - i = 0; - while (i <= max_index) { // BAD - i++; - } -} - -void test6() { - int i = 1; - while (i > 0) { // GOOD - &i; - } -} - -void test7(bool b) { - int i = 1; - while (b) { // BAD - while (i > 0) { // BAD - &i; - } - } +// GOOD = at least one iteration +// BAD = possibly no iterations + +void test1() { + bool done = false; + while (!done) { // GOOD + done = true; + } +} + +void test2() { + bool done = true; + done = false; + while (!done) { // GOOD (NOT REPORTED) + done = true; + } +} + +void test3(int i) { + bool done = false; + for (; i++; i < 10) { + while (!done) { // BAD + done = true; + } + } +} + +void test4(int i) { + for (; i++; i < 10) { + bool done = false; + while (!done) { // GOOD + done = true; + } + } +} + +void test5(int max) { + int i = 0, k = 0; + int max_index = 0; + while (i < max) { // BAD + max_index = i; + i++; + } + i = 0; + while (i <= max_index) { // BAD + i++; + } +} + +void test6() { + int i = 1; + while (i > 0) { // GOOD + &i; + } +} + +void test7(bool b) { + int i = 1; + while (b) { // BAD + while (i > 0) { // BAD + &i; + } + } } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/conversions/conversions.cpp b/cpp/ql/test/library-tests/conversions/conversions.cpp index 4fb1fa3c200..b9cdb8df02a 100644 --- a/cpp/ql/test/library-tests/conversions/conversions.cpp +++ b/cpp/ql/test/library-tests/conversions/conversions.cpp @@ -1,250 +1,250 @@ -typedef unsigned short ushort; - -enum E { - E0, - E1 -}; - -enum class EC : int { - EC0, - EC1 -}; - -void ArithmeticConversions() { - char c = 0; - unsigned char uc = 0; - short s = 0; - unsigned short us = 0; - int i = 0; - unsigned int ui = 0; - long l = 0; - unsigned long ul = 0; - long long ll = 0; - unsigned long long ull = 0; - float f = 0; - double d = 0; - wchar_t wc = 0; - E e{}; - EC ec{}; - - c = uc; - c = (char)uc; - c = char(uc); - c = static_cast(uc); - i = s; - i = (int)s; - i = int(s); - i = static_cast(s); - us = i; - us = (unsigned short)i; - us = ushort(i); - us = static_cast(i); - - i = d; - i = (int)d; - i = int(d); - i = static_cast(d); - - f = c; - f = (float)c; - f = float(c); - f = static_cast(c); - - f = d; - f = (float)d; - f = float(d); - f = static_cast(d); - - d = f; - d = (double)f; - d = double(f); - d = static_cast(f); - - i = E0; - i = e; - i = static_cast(EC::EC0); - i = static_cast(ec); - e = static_cast(i); - ec = static_cast(i); -} - -struct S { - int x; - double y; -}; - -void ConversionsToBool() { - bool b = 0; - int i = 0; - double d = 0; - void* p = nullptr; - int S::* pmd = nullptr; - - if (b) { - } - else if ((bool)b) { - } - else if (i) { - } - else if (d) { - } - else if (p) { - } - else if (pmd) { - } -} - -struct Base { - int b1; - void BaseMethod(); -}; - -struct Middle : Base { - int m1; - void MiddleMethod(); -}; - -struct Derived : Middle { - int d1; - void DerivedMethod(); -}; - -void HierarchyCasts() { - Base b; - Middle m; - Derived d; - - Base* pb = &b; - Middle* pm = &m; - Derived* pd = &d; - - b = m; - b = (Base)m; - b = static_cast(m); - pb = pm; - pb = (Base*)pm; - pb = static_cast(pm); - pb = reinterpret_cast(pm); - - m = (Middle&)b; - m = static_cast(b); - pm = (Middle*)pb; - pm = static_cast(pb); - pm = reinterpret_cast(pb); - - b = d; - b = (Base)d; - b = static_cast(d); - pb = pd; - pb = (Base*)pd; - pb = static_cast(pd); - pb = reinterpret_cast(pd); - - d = (Derived&)b; - d = static_cast(b); - pd = (Derived*)pb; - pd = static_cast(pb); - pd = reinterpret_cast(pb); -} - -void PTMCasts() { - int Base::* pb = &Base::b1; - void (Base::* pmfb)() = &Base::BaseMethod; - int Middle::* pm = &Middle::m1; - void (Middle::* pmfm)() = &Middle::MiddleMethod; - int Derived::* pd = &Derived::d1; - void (Derived::* pmfd)() = &Derived::DerivedMethod; - - pb = (int Base::*)pm; - pmfb = (void (Base::*)())pmfm; - pb = static_cast(pm); - pmfb = static_cast(pmfm); - - pm = pb; - pmfm = pmfb; - pm = (int Middle::*)pb; - pmfm = (void (Middle::*)())pmfb; - pm = static_cast(pb); - pmfm = static_cast(pmfb); - - pb = (int Base::*)pd; - pmfb = (void (Base::*)())pmfd; - pb = static_cast(pd); - pmfb = static_cast(pmfd); - - pd = pb; - pmfd = pmfb; - pd = (int Derived::*)pb; - pmfd = (void (Derived::*)())pmfb; - pd = static_cast(pb); - pmfd = static_cast(pmfb); -} - -struct String { - String(); - String(const String&); - ~String(); -}; - -void Adjust() { - const String& s1 = String(); // prvalue adjustment - Base b; - Derived d; - const Base& rb = true ? b : d; // glvalue adjustment - const Base& r = (Base&)s1; -} - -void QualificationConversions() { - const int* pc = nullptr; - const volatile int* pcv = nullptr; - pcv = pc; - pc = const_cast(pcv); -} - -void PointerIntegralConversions() { - void* p = nullptr; - long n = (long)p; - n = reinterpret_cast(p); - p = (void*)n; - p = reinterpret_cast(n); -} - -struct PolymorphicBase { - virtual ~PolymorphicBase(); -}; - -struct PolymorphicDerived : PolymorphicBase { -}; - -void DynamicCast() { - PolymorphicBase b; - PolymorphicDerived d; - - PolymorphicBase* pb = &b; - 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. - pb = dynamic_cast(pd); - PolymorphicBase& rb = dynamic_cast(d); - - pd = dynamic_cast(pb); - PolymorphicDerived& rd = dynamic_cast(b); -} - -void FuncPtrConversions(int(*pfn)(int), void* p) { - p = (void*)pfn; - pfn = (int(*)(int))p; -} - -int Func(); - -void ConversionsToVoid() { - int x; - (void)x; - static_cast(x); - (void)Func(); - static_cast(Func()); - (void)1; - static_cast(1); -} - +typedef unsigned short ushort; + +enum E { + E0, + E1 +}; + +enum class EC : int { + EC0, + EC1 +}; + +void ArithmeticConversions() { + char c = 0; + unsigned char uc = 0; + short s = 0; + unsigned short us = 0; + int i = 0; + unsigned int ui = 0; + long l = 0; + unsigned long ul = 0; + long long ll = 0; + unsigned long long ull = 0; + float f = 0; + double d = 0; + wchar_t wc = 0; + E e{}; + EC ec{}; + + c = uc; + c = (char)uc; + c = char(uc); + c = static_cast(uc); + i = s; + i = (int)s; + i = int(s); + i = static_cast(s); + us = i; + us = (unsigned short)i; + us = ushort(i); + us = static_cast(i); + + i = d; + i = (int)d; + i = int(d); + i = static_cast(d); + + f = c; + f = (float)c; + f = float(c); + f = static_cast(c); + + f = d; + f = (float)d; + f = float(d); + f = static_cast(d); + + d = f; + d = (double)f; + d = double(f); + d = static_cast(f); + + i = E0; + i = e; + i = static_cast(EC::EC0); + i = static_cast(ec); + e = static_cast(i); + ec = static_cast(i); +} + +struct S { + int x; + double y; +}; + +void ConversionsToBool() { + bool b = 0; + int i = 0; + double d = 0; + void* p = nullptr; + int S::* pmd = nullptr; + + if (b) { + } + else if ((bool)b) { + } + else if (i) { + } + else if (d) { + } + else if (p) { + } + else if (pmd) { + } +} + +struct Base { + int b1; + void BaseMethod(); +}; + +struct Middle : Base { + int m1; + void MiddleMethod(); +}; + +struct Derived : Middle { + int d1; + void DerivedMethod(); +}; + +void HierarchyCasts() { + Base b; + Middle m; + Derived d; + + Base* pb = &b; + Middle* pm = &m; + Derived* pd = &d; + + b = m; + b = (Base)m; + b = static_cast(m); + pb = pm; + pb = (Base*)pm; + pb = static_cast(pm); + pb = reinterpret_cast(pm); + + m = (Middle&)b; + m = static_cast(b); + pm = (Middle*)pb; + pm = static_cast(pb); + pm = reinterpret_cast(pb); + + b = d; + b = (Base)d; + b = static_cast(d); + pb = pd; + pb = (Base*)pd; + pb = static_cast(pd); + pb = reinterpret_cast(pd); + + d = (Derived&)b; + d = static_cast(b); + pd = (Derived*)pb; + pd = static_cast(pb); + pd = reinterpret_cast(pb); +} + +void PTMCasts() { + int Base::* pb = &Base::b1; + void (Base::* pmfb)() = &Base::BaseMethod; + int Middle::* pm = &Middle::m1; + void (Middle::* pmfm)() = &Middle::MiddleMethod; + int Derived::* pd = &Derived::d1; + void (Derived::* pmfd)() = &Derived::DerivedMethod; + + pb = (int Base::*)pm; + pmfb = (void (Base::*)())pmfm; + pb = static_cast(pm); + pmfb = static_cast(pmfm); + + pm = pb; + pmfm = pmfb; + pm = (int Middle::*)pb; + pmfm = (void (Middle::*)())pmfb; + pm = static_cast(pb); + pmfm = static_cast(pmfb); + + pb = (int Base::*)pd; + pmfb = (void (Base::*)())pmfd; + pb = static_cast(pd); + pmfb = static_cast(pmfd); + + pd = pb; + pmfd = pmfb; + pd = (int Derived::*)pb; + pmfd = (void (Derived::*)())pmfb; + pd = static_cast(pb); + pmfd = static_cast(pmfb); +} + +struct String { + String(); + String(const String&); + ~String(); +}; + +void Adjust() { + const String& s1 = String(); // prvalue adjustment + Base b; + Derived d; + const Base& rb = true ? b : d; // glvalue adjustment + const Base& r = (Base&)s1; +} + +void QualificationConversions() { + const int* pc = nullptr; + const volatile int* pcv = nullptr; + pcv = pc; + pc = const_cast(pcv); +} + +void PointerIntegralConversions() { + void* p = nullptr; + long n = (long)p; + n = reinterpret_cast(p); + p = (void*)n; + p = reinterpret_cast(n); +} + +struct PolymorphicBase { + virtual ~PolymorphicBase(); +}; + +struct PolymorphicDerived : PolymorphicBase { +}; + +void DynamicCast() { + PolymorphicBase b; + PolymorphicDerived d; + + PolymorphicBase* pb = &b; + 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. + pb = dynamic_cast(pd); + PolymorphicBase& rb = dynamic_cast(d); + + pd = dynamic_cast(pb); + PolymorphicDerived& rd = dynamic_cast(b); +} + +void FuncPtrConversions(int(*pfn)(int), void* p) { + p = (void*)pfn; + pfn = (int(*)(int))p; +} + +int Func(); + +void ConversionsToVoid() { + int x; + (void)x; + static_cast(x); + (void)Func(); + static_cast(Func()); + (void)1; + static_cast(1); +} + diff --git a/cpp/ql/test/library-tests/ctorinits/ctorinits.cpp b/cpp/ql/test/library-tests/ctorinits/ctorinits.cpp index 6d39d6a393c..13d0e1e4b01 100644 --- a/cpp/ql/test/library-tests/ctorinits/ctorinits.cpp +++ b/cpp/ql/test/library-tests/ctorinits/ctorinits.cpp @@ -45,53 +45,53 @@ private: int xs[4]; }; -struct A { - A(int); -}; - -struct B { - B(int); -}; - -struct C { - C(int); -}; - -struct MultipleBases : A, B, C { - int x; - int y; - int z; - - MultipleBases() : - z(5), - B(1), - x(3), - A(0), - C(2), - y(4) { - } -}; - -struct VB { +struct A { + A(int); +}; + +struct B { + B(int); +}; + +struct C { + C(int); +}; + +struct MultipleBases : A, B, C { + int x; + int y; + int z; + + MultipleBases() : + z(5), + B(1), + x(3), + A(0), + C(2), + y(4) { + } +}; + +struct VB { VB(); VB(int); ~VB(); }; -struct VD : virtual VB { -}; - -struct VirtualAndNonVirtual : VD, VB { - VirtualAndNonVirtual() { - } - ~VirtualAndNonVirtual() { - } -}; - -struct AllYourVirtualBaseAreBelongToUs : VD, VirtualAndNonVirtual, virtual VB { - AllYourVirtualBaseAreBelongToUs() : - VB(5) { - } - ~AllYourVirtualBaseAreBelongToUs() { - } +struct VD : virtual VB { +}; + +struct VirtualAndNonVirtual : VD, VB { + VirtualAndNonVirtual() { + } + ~VirtualAndNonVirtual() { + } +}; + +struct AllYourVirtualBaseAreBelongToUs : VD, VirtualAndNonVirtual, virtual VB { + AllYourVirtualBaseAreBelongToUs() : + VB(5) { + } + ~AllYourVirtualBaseAreBelongToUs() { + } }; \ No newline at end of file diff --git a/cpp/ql/test/library-tests/declarationEntry/template/src5.cpp b/cpp/ql/test/library-tests/declarationEntry/template/src5.cpp index 8fc3e31ad72..3e5111f09bf 100644 --- a/cpp/ql/test/library-tests/declarationEntry/template/src5.cpp +++ b/cpp/ql/test/library-tests/declarationEntry/template/src5.cpp @@ -1,10 +1,10 @@ -// src5.cpp - -#include "src5.fwd.hpp" - -template - class my_istream { - }; - -template <> - class my_istream; +// src5.cpp + +#include "src5.fwd.hpp" + +template + class my_istream { + }; + +template <> + class my_istream; diff --git a/cpp/ql/test/library-tests/declarationEntry/template/src5.fwd.hpp b/cpp/ql/test/library-tests/declarationEntry/template/src5.fwd.hpp index 770189f7266..8a7cec05bca 100644 --- a/cpp/ql/test/library-tests/declarationEntry/template/src5.fwd.hpp +++ b/cpp/ql/test/library-tests/declarationEntry/template/src5.fwd.hpp @@ -1,8 +1,8 @@ -// src5.fwd.hpp - -#ifndef SRC5_FWD_HPP -#define SRC5_FWD_HPP - - template class my_istream; - -#endif // SRC5_FWD_HPP +// src5.fwd.hpp + +#ifndef SRC5_FWD_HPP +#define SRC5_FWD_HPP + + template class my_istream; + +#endif // SRC5_FWD_HPP diff --git a/cpp/ql/test/library-tests/declarationEntry/template/src6.cpp b/cpp/ql/test/library-tests/declarationEntry/template/src6.cpp index 729a25f5049..2bb70e22f22 100644 --- a/cpp/ql/test/library-tests/declarationEntry/template/src6.cpp +++ b/cpp/ql/test/library-tests/declarationEntry/template/src6.cpp @@ -1,5 +1,5 @@ -// src6.cpp - -#include "src5.fwd.hpp" - -my_istream *mis_c; +// src6.cpp + +#include "src5.fwd.hpp" + +my_istream *mis_c; diff --git a/cpp/ql/test/library-tests/depends_addressable/addressable.cpp b/cpp/ql/test/library-tests/depends_addressable/addressable.cpp index 40de1850c7e..a6c22730002 100644 --- a/cpp/ql/test/library-tests/depends_addressable/addressable.cpp +++ b/cpp/ql/test/library-tests/depends_addressable/addressable.cpp @@ -1,28 +1,28 @@ -class A { -public: - A() {} -}; - -A a; -void f() {} - - -class Test { - A aa; - - void fa() {} - - void test() { - void (*fptr)(); - void (Test::*mfptr)(); - void *ptr; - - ptr = &a; - ptr = &aa; - - fptr = f; // same as below - fptr = &f; // same as above - mfptr = &Test::fa; - - } -}; +class A { +public: + A() {} +}; + +A a; +void f() {} + + +class Test { + A aa; + + void fa() {} + + void test() { + void (*fptr)(); + void (Test::*mfptr)(); + void *ptr; + + ptr = &a; + ptr = &aa; + + fptr = f; // same as below + fptr = &f; // same as above + mfptr = &Test::fa; + + } +}; diff --git a/cpp/ql/test/library-tests/depends_friends/friends.cpp b/cpp/ql/test/library-tests/depends_friends/friends.cpp index 1acdd763a90..2335b0829e1 100644 --- a/cpp/ql/test/library-tests/depends_friends/friends.cpp +++ b/cpp/ql/test/library-tests/depends_friends/friends.cpp @@ -1,28 +1,28 @@ -class Friend1 { -public: - void f(); -protected: - void g(); -private: - void h(); -}; - -class Friend2 { -public: - void f(); -protected: - void g(); -private: - void h(); -}; - -void Friend2::f() { -} - -void friendFunc() {} - -class C { - friend class Friend1; - friend void Friend2::f(); - friend void friendFunc(); -}; +class Friend1 { +public: + void f(); +protected: + void g(); +private: + void h(); +}; + +class Friend2 { +public: + void f(); +protected: + void g(); +private: + void h(); +}; + +void Friend2::f() { +} + +void friendFunc() {} + +class C { + friend class Friend1; + friend void Friend2::f(); + friend void friendFunc(); +}; diff --git a/cpp/ql/test/library-tests/depends_initializers/initializers.cpp b/cpp/ql/test/library-tests/depends_initializers/initializers.cpp index 079398e20bc..85a83d245eb 100644 --- a/cpp/ql/test/library-tests/depends_initializers/initializers.cpp +++ b/cpp/ql/test/library-tests/depends_initializers/initializers.cpp @@ -1,31 +1,31 @@ -//references(UserType) -class A { -public: - A() {} -}; - -int f() { - void *a_ptr = new A(); //match (1 call) - A a = A(); // match (1 call) - return 1; -} - -//calls(Function) -int g() {return 0;} -extern int h(); - -int x = g(); //match -int y = x + g(); //match (1 call, 1 access) -int z = x + g() + h(); //match(2 calls, 1 access) - -//accesses(Variable) -int i = 1; -int j = i; //match (1 access) - -A a; //match(1 call) -A ax = A(); //match (1 call) -A aax = ax; //match (1 access) - -//array initialization -int myIntArray[5] = {i, 0, 0, 0, 0}; //match(1 access) -A myObjectArray[3]; //match(1 call) +//references(UserType) +class A { +public: + A() {} +}; + +int f() { + void *a_ptr = new A(); //match (1 call) + A a = A(); // match (1 call) + return 1; +} + +//calls(Function) +int g() {return 0;} +extern int h(); + +int x = g(); //match +int y = x + g(); //match (1 call, 1 access) +int z = x + g() + h(); //match(2 calls, 1 access) + +//accesses(Variable) +int i = 1; +int j = i; //match (1 access) + +A a; //match(1 call) +A ax = A(); //match (1 call) +A aax = ax; //match (1 access) + +//array initialization +int myIntArray[5] = {i, 0, 0, 0, 0}; //match(1 access) +A myObjectArray[3]; //match(1 call) diff --git a/cpp/ql/test/library-tests/depends_initializers/template_static.cpp b/cpp/ql/test/library-tests/depends_initializers/template_static.cpp index 956cd767d63..4bc6a869fce 100644 --- a/cpp/ql/test/library-tests/depends_initializers/template_static.cpp +++ b/cpp/ql/test/library-tests/depends_initializers/template_static.cpp @@ -1,89 +1,89 @@ - -const int c = 1; -int v = 1; -int one() {return 1;} - -void myNormalFunction() -{ - static int static_1 = 1; - static int static_c = c; - static int static_v = v; - static int static_one = one(); - int local_1 = 1; - int local_c = c; - int local_v = v; - int local_one = one(); -} - -template void myTemplateFunction() -{ - static int static_int_1 = 1; - static int static_int_c = c; // [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 T static_t_1 = 1; // [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_one = one(); // [initializer is not populated] - - int local_int_1 = 1; - int local_int_c = c; - int local_int_v = v; - int local_int_one = one(); - T local_t_1 = 1; - T local_t_c = c; - T local_t_v = v; - T local_t_one = one(); -} - -template class myTemplateClass -{ -public: - void myMethod() - { - static int static_int_1 = 1; - static int static_int_c = c; // [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 T static_t_1 = 1; // [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_one = one(); // [initializer is not populated] - - int local_int_1 = 1; - int local_int_c = c; - int local_int_v = v; - int local_int_one = one(); - T local_t_1 = 1; - T local_t_c = c; - T local_t_v = v; - T local_t_one = one(); - } -}; - -enum myEnum -{ - MYENUM_CONST -}; - -template void myTemplateFunction2(int a = 1, T b = 2) -{ - static int static_int_zero = 0; - static int static_int_ec = MYENUM_CONST; - static int static_int_expr = v + 1; - static int *static_int_addr = &v; - static int static_int_sizeof_v = sizeof(v); - static int static_int_sizeof_t = sizeof(T); - static T static_t_zero = 0; - static T static_t_ec = MYENUM_CONST; - static T static_t_expr = v + 1; - static T *static_t_addr = &v; - static T static_t_sizeof_v = sizeof(v); - static T static_t_sizeof_t = sizeof(T); - - static int static_int_c1 = c; - static int static_int_c2=c; - { - static int static_int_v2 = v; - } -} + +const int c = 1; +int v = 1; +int one() {return 1;} + +void myNormalFunction() +{ + static int static_1 = 1; + static int static_c = c; + static int static_v = v; + static int static_one = one(); + int local_1 = 1; + int local_c = c; + int local_v = v; + int local_one = one(); +} + +template void myTemplateFunction() +{ + static int static_int_1 = 1; + static int static_int_c = c; // [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 T static_t_1 = 1; // [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_one = one(); // [initializer is not populated] + + int local_int_1 = 1; + int local_int_c = c; + int local_int_v = v; + int local_int_one = one(); + T local_t_1 = 1; + T local_t_c = c; + T local_t_v = v; + T local_t_one = one(); +} + +template class myTemplateClass +{ +public: + void myMethod() + { + static int static_int_1 = 1; + static int static_int_c = c; // [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 T static_t_1 = 1; // [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_one = one(); // [initializer is not populated] + + int local_int_1 = 1; + int local_int_c = c; + int local_int_v = v; + int local_int_one = one(); + T local_t_1 = 1; + T local_t_c = c; + T local_t_v = v; + T local_t_one = one(); + } +}; + +enum myEnum +{ + MYENUM_CONST +}; + +template void myTemplateFunction2(int a = 1, T b = 2) +{ + static int static_int_zero = 0; + static int static_int_ec = MYENUM_CONST; + static int static_int_expr = v + 1; + static int *static_int_addr = &v; + static int static_int_sizeof_v = sizeof(v); + static int static_int_sizeof_t = sizeof(T); + static T static_t_zero = 0; + static T static_t_ec = MYENUM_CONST; + static T static_t_expr = v + 1; + static T *static_t_addr = &v; + static T static_t_sizeof_v = sizeof(v); + static T static_t_sizeof_t = sizeof(T); + + static int static_int_c1 = c; + static int static_int_c2=c; + { + static int static_int_v2 = v; + } +} diff --git a/cpp/ql/test/library-tests/depends_initializers/template_static_instantiated.cpp b/cpp/ql/test/library-tests/depends_initializers/template_static_instantiated.cpp index 06d5ae355fd..ad703eee4af 100644 --- a/cpp/ql/test/library-tests/depends_initializers/template_static_instantiated.cpp +++ b/cpp/ql/test/library-tests/depends_initializers/template_static_instantiated.cpp @@ -1,74 +1,74 @@ -namespace ns2 { -const int c = 1; -int v = 1; -int one() {return 1;} - -void myNormalFunction() -{ - static int static_1 = 1; - static int static_c = c; - static int static_v = v; - static int static_one = one(); - int local_1 = 1; - int local_c = c; - int local_v = v; - int local_one = one(); -} - -template void myTemplateFunction() -{ - static int static_int_1 = 1; - static int static_int_c = c; // [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 T static_t_1 = 1; // [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_one = one(); // [initializer is not populated] - - int local_int_1 = 1; - int local_int_c = c; - int local_int_v = v; - int local_int_one = one(); - T local_t_1 = 1; - T local_t_c = c; - T local_t_v = v; - T local_t_one = one(); -} - -template class myTemplateClass -{ -public: - void myMethod() - { - static int static_int_1 = 1; - static int static_int_c = c; // [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 T static_t_1 = 1; // [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_one = one(); // [initializer is not populated] - - int local_int_1 = 1; - int local_int_c = c; - int local_int_v = v; - int local_int_one = one(); - T local_t_1 = 1; - T local_t_c = c; - T local_t_v = v; - T local_t_one = one(); - } -}; - -void testFunc() -{ - // instantiate the templates - myTemplateFunction(); - - { - myTemplateClass mtc; - mtc.myMethod(); - } -} -} +namespace ns2 { +const int c = 1; +int v = 1; +int one() {return 1;} + +void myNormalFunction() +{ + static int static_1 = 1; + static int static_c = c; + static int static_v = v; + static int static_one = one(); + int local_1 = 1; + int local_c = c; + int local_v = v; + int local_one = one(); +} + +template void myTemplateFunction() +{ + static int static_int_1 = 1; + static int static_int_c = c; // [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 T static_t_1 = 1; // [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_one = one(); // [initializer is not populated] + + int local_int_1 = 1; + int local_int_c = c; + int local_int_v = v; + int local_int_one = one(); + T local_t_1 = 1; + T local_t_c = c; + T local_t_v = v; + T local_t_one = one(); +} + +template class myTemplateClass +{ +public: + void myMethod() + { + static int static_int_1 = 1; + static int static_int_c = c; // [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 T static_t_1 = 1; // [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_one = one(); // [initializer is not populated] + + int local_int_1 = 1; + int local_int_c = c; + int local_int_v = v; + int local_int_one = one(); + T local_t_1 = 1; + T local_t_c = c; + T local_t_v = v; + T local_t_one = one(); + } +}; + +void testFunc() +{ + // instantiate the templates + myTemplateFunction(); + + { + myTemplateClass mtc; + mtc.myMethod(); + } +} +} diff --git a/cpp/ql/test/library-tests/derived_types/derivedtype.cpp b/cpp/ql/test/library-tests/derived_types/derivedtype.cpp index 496901e6e09..1f71350d5cd 100644 --- a/cpp/ql/test/library-tests/derived_types/derivedtype.cpp +++ b/cpp/ql/test/library-tests/derived_types/derivedtype.cpp @@ -1,9 +1,9 @@ -class C { - C() {} -}; - -typedef C CC; - -CC** f() { - return 0; -} +class C { + C() {} +}; + +typedef C CC; + +CC** f() { + return 0; +} diff --git a/cpp/ql/test/library-tests/enums/enums/enums.cpp b/cpp/ql/test/library-tests/enums/enums/enums.cpp index 1fb523eca80..8404970fa3a 100644 --- a/cpp/ql/test/library-tests/enums/enums/enums.cpp +++ b/cpp/ql/test/library-tests/enums/enums/enums.cpp @@ -1,15 +1,15 @@ -const int j = 0; - -enum Day { sun, mon, tue, wed, thu, fri, sat }; -enum Day2 { sun2 = j, mon2, tue2 }; -enum Flag { b = 'a', c = 'b', d = 'd' }; - -Day& operator++(Day& d) -{ - int i = d; - Flag f = Flag(7); - Flag g = Flag(8); - //const int *p = &sat; - Day2 d2 = (Day2)d; - return d = (sat==d) ? sun: Day(d+1); -} +const int j = 0; + +enum Day { sun, mon, tue, wed, thu, fri, sat }; +enum Day2 { sun2 = j, mon2, tue2 }; +enum Flag { b = 'a', c = 'b', d = 'd' }; + +Day& operator++(Day& d) +{ + int i = d; + Flag f = Flag(7); + Flag g = Flag(8); + //const int *p = &sat; + Day2 d2 = (Day2)d; + return d = (sat==d) ? sun: Day(d+1); +} diff --git a/cpp/ql/test/library-tests/exprs/comparison_operation/test.cpp b/cpp/ql/test/library-tests/exprs/comparison_operation/test.cpp index 0735583e171..8fd8cb45172 100644 --- a/cpp/ql/test/library-tests/exprs/comparison_operation/test.cpp +++ b/cpp/ql/test/library-tests/exprs/comparison_operation/test.cpp @@ -1,14 +1,14 @@ - -int main() -{ - int x; - - if (x == 1) {} - if (x != 1) {} - if (x < 1) {} - if (x > 1) {} - if (x <= 1) {} - if (x >= 1) {} - - return 0; -} + +int main() +{ + int x; + + if (x == 1) {} + if (x != 1) {} + if (x < 1) {} + if (x > 1) {} + if (x <= 1) {} + if (x >= 1) {} + + return 0; +} diff --git a/cpp/ql/test/library-tests/exprs/unary_operation/test.cpp b/cpp/ql/test/library-tests/exprs/unary_operation/test.cpp index 8b33083b13f..2400527d174 100644 --- a/cpp/ql/test/library-tests/exprs/unary_operation/test.cpp +++ b/cpp/ql/test/library-tests/exprs/unary_operation/test.cpp @@ -1,15 +1,15 @@ - -int main() -{ - int i; - int *ip; - - i = +(-1); - i++; - ip = &i; - *ip--; - ++i; - --i; - - return 0; -} + +int main() +{ + int i; + int *ip; + + i = +(-1); + i++; + ip = &i; + *ip--; + ++i; + --i; + + return 0; +} diff --git a/cpp/ql/test/library-tests/exprs/value_categories/value_categories.cpp b/cpp/ql/test/library-tests/exprs/value_categories/value_categories.cpp index 05cd6c16583..bf0a6176948 100644 --- a/cpp/ql/test/library-tests/exprs/value_categories/value_categories.cpp +++ b/cpp/ql/test/library-tests/exprs/value_categories/value_categories.cpp @@ -1,155 +1,155 @@ -int ParamsAndLocals(int x) -{ - int y; - - // y is an lvalue, as is the result of the assignment. x is a load. - y = x + 1; - - // y is a load. - return y; -} - -int Dereference(int* p, int *q) -{ - // *p is an lvalue, as is the result of the assignment. - // p, q, and *q are loads. - *p = *q; - - int x = 5; - - // x is an lvalue. - // *&x is a load. - return *&x; -} - -int& References(int& r) -{ - // The reference r is a load, as is the result of dereferencing the - // reference r. - int x = r; - - // The result of dereferencing the reference r is an lvalue. - // The reference r is a load. - int* p = &r; - - // The result of deferencing the reference r is an lvalue, as is the result - // of the assignment. - // The reference r is a load. - r = 5; - - // The result of dereferencing the reference r is an lvalue. - // The reference r is a load. - return r; -} - -int&& GetRValueRef(); -void CallRValueRef(int&& rr); - -int&& RValueReferences(int&& rr) -{ - // The result of dereferencing the reference returned by GetRValueRef() is - // an xvalue. - CallRValueRef(GetRValueRef()); - - // The result of dereferencing the reference rr is an lvalue, as is the - // result of the assignment. - // The reference rr is a load. - rr = 5; - - // The result of the static cast is an xvalue. The result of dereferencing - // the reference rr is an lvalue. - // The reference rr is a load. - return static_cast(rr); -} - -struct S -{ - int MemberFunction(); -}; - -int CallMemberFunction(S& s) -{ - // The result of dereferencing the reference s is an lvalue. - // The reference s is a load. - return s.MemberFunction(); -} - -int Func(); -void AddressOfFunc() -{ - // Func is a load due to the function-to-function-pointer conversions. - int (*p)() = Func; -} - -struct T -{ - int x; - int y; - int MemberFunc(float); -}; - -void FieldAccesses() -{ - T t; - // t, t.x, and the assignment are all lvalues. - t.x = 0; - // t is an lvalue. - // t.x is a load. - int a = t.x; -} - -void StringLiterals() -{ - // All string literals are lvalues - "String"; - const char* p = "String"; - const char (&a)[7] = "String"; - // The array access is a load - char c = "String"[1]; -} - -void Crement() -{ - int x = 0; - // x is an lvalue. - x++; - // x is an lvalue. - x--; - // x is an lvalue, as is the result of ++x. - ++x; - // x is an lvalue, as is the result of --x. - --x; -} - -void CompoundAssignment() -{ - int x = 0; - - // x is an lvalue, as is the result of x += 1 - x += 1; - // x is an lvalue, as is the result of x -= 1 - x -= 1; - // x is an lvalue, as is the result of x *= 1 - x *= 1; - // x is an lvalue, as is the result of x /= 1 - x /= 1; - // x is an lvalue, as is the result of x %= 1 - x %= 1; - // x is an lvalue, as is the result of x <<= 1 - x <<= 1; - // x is an lvalue, as is the result of x >>= 1 - x >>= 1; - // x is an lvalue, as is the result of x |= 1 - x |= 1; - // x is an lvalue, as is the result of x &= 1 - x &= 1; - // x is an lvalue, as is the result of x ^= 1 - x ^= 1; -} - -void PointerToMemberLiteral() -{ - // All pointer-to-member literals are prvalues - int T::* pmd = &T::x; - int (T::* pmf)(float) = &T::MemberFunc; -} +int ParamsAndLocals(int x) +{ + int y; + + // y is an lvalue, as is the result of the assignment. x is a load. + y = x + 1; + + // y is a load. + return y; +} + +int Dereference(int* p, int *q) +{ + // *p is an lvalue, as is the result of the assignment. + // p, q, and *q are loads. + *p = *q; + + int x = 5; + + // x is an lvalue. + // *&x is a load. + return *&x; +} + +int& References(int& r) +{ + // The reference r is a load, as is the result of dereferencing the + // reference r. + int x = r; + + // The result of dereferencing the reference r is an lvalue. + // The reference r is a load. + int* p = &r; + + // The result of deferencing the reference r is an lvalue, as is the result + // of the assignment. + // The reference r is a load. + r = 5; + + // The result of dereferencing the reference r is an lvalue. + // The reference r is a load. + return r; +} + +int&& GetRValueRef(); +void CallRValueRef(int&& rr); + +int&& RValueReferences(int&& rr) +{ + // The result of dereferencing the reference returned by GetRValueRef() is + // an xvalue. + CallRValueRef(GetRValueRef()); + + // The result of dereferencing the reference rr is an lvalue, as is the + // result of the assignment. + // The reference rr is a load. + rr = 5; + + // The result of the static cast is an xvalue. The result of dereferencing + // the reference rr is an lvalue. + // The reference rr is a load. + return static_cast(rr); +} + +struct S +{ + int MemberFunction(); +}; + +int CallMemberFunction(S& s) +{ + // The result of dereferencing the reference s is an lvalue. + // The reference s is a load. + return s.MemberFunction(); +} + +int Func(); +void AddressOfFunc() +{ + // Func is a load due to the function-to-function-pointer conversions. + int (*p)() = Func; +} + +struct T +{ + int x; + int y; + int MemberFunc(float); +}; + +void FieldAccesses() +{ + T t; + // t, t.x, and the assignment are all lvalues. + t.x = 0; + // t is an lvalue. + // t.x is a load. + int a = t.x; +} + +void StringLiterals() +{ + // All string literals are lvalues + "String"; + const char* p = "String"; + const char (&a)[7] = "String"; + // The array access is a load + char c = "String"[1]; +} + +void Crement() +{ + int x = 0; + // x is an lvalue. + x++; + // x is an lvalue. + x--; + // x is an lvalue, as is the result of ++x. + ++x; + // x is an lvalue, as is the result of --x. + --x; +} + +void CompoundAssignment() +{ + int x = 0; + + // x is an lvalue, as is the result of x += 1 + x += 1; + // x is an lvalue, as is the result of x -= 1 + x -= 1; + // x is an lvalue, as is the result of x *= 1 + x *= 1; + // x is an lvalue, as is the result of x /= 1 + x /= 1; + // x is an lvalue, as is the result of x %= 1 + x %= 1; + // x is an lvalue, as is the result of x <<= 1 + x <<= 1; + // x is an lvalue, as is the result of x >>= 1 + x >>= 1; + // x is an lvalue, as is the result of x |= 1 + x |= 1; + // x is an lvalue, as is the result of x &= 1 + x &= 1; + // x is an lvalue, as is the result of x ^= 1 + x ^= 1; +} + +void PointerToMemberLiteral() +{ + // All pointer-to-member literals are prvalues + int T::* pmd = &T::x; + int (T::* pmf)(float) = &T::MemberFunc; +} diff --git a/cpp/ql/test/library-tests/exprs_basic/exprs_basic1.cpp b/cpp/ql/test/library-tests/exprs_basic/exprs_basic1.cpp index a1190b7955d..159336371b4 100644 --- a/cpp/ql/test/library-tests/exprs_basic/exprs_basic1.cpp +++ b/cpp/ql/test/library-tests/exprs_basic/exprs_basic1.cpp @@ -1,33 +1,33 @@ -enum Type { S, I }; - -struct Foo { - char* name; - int count; - char* another_name; - char* yet_another_name; - char initials[2]; - long very_long; -}; - -void create_foo() -{ - Foo xx; - char name[] = "Foo McFoo"; - xx.name = name; - xx.count = 123; - Foo yy = { "Barry McBar", 42, "Baz", "Basildon", { 'B', 'X' }, 5678 }; -} - -void print_foo(Foo* p) -{ - -} - -Foo current_foo; - -Foo set_current_foo(Foo next) -{ - Foo prev = current_foo; - current_foo = next; - return prev; -} +enum Type { S, I }; + +struct Foo { + char* name; + int count; + char* another_name; + char* yet_another_name; + char initials[2]; + long very_long; +}; + +void create_foo() +{ + Foo xx; + char name[] = "Foo McFoo"; + xx.name = name; + xx.count = 123; + Foo yy = { "Barry McBar", 42, "Baz", "Basildon", { 'B', 'X' }, 5678 }; +} + +void print_foo(Foo* p) +{ + +} + +Foo current_foo; + +Foo set_current_foo(Foo next) +{ + Foo prev = current_foo; + current_foo = next; + return prev; +} diff --git a/cpp/ql/test/library-tests/exprs_cast/options b/cpp/ql/test/library-tests/exprs_cast/options index 6158faf8d2f..d8db22a4bcb 100644 --- a/cpp/ql/test/library-tests/exprs_cast/options +++ b/cpp/ql/test/library-tests/exprs_cast/options @@ -1 +1 @@ -semmle-extractor-options: --edg --target --edg win64 +semmle-extractor-options: --edg --target --edg win64 diff --git a/cpp/ql/test/library-tests/fields/fields/fields.cpp b/cpp/ql/test/library-tests/fields/fields/fields.cpp index c4e26495b4c..ce65bee0afe 100644 --- a/cpp/ql/test/library-tests/fields/fields/fields.cpp +++ b/cpp/ql/test/library-tests/fields/fields/fields.cpp @@ -1,33 +1,33 @@ -enum Type { S, I }; - -struct Entry { - char* name; - Type t; - char* s; - int i; -private: - int internal; -}; - -class Name { - const char* s; -}; - -class Table { - Name* p; - int sz; -public: - Table(int s=15) { p = new Name[sz=s]; } // constructor - ~Table() { delete[] p; } - Name* lookup (const char*); - bool insert(Name*); -}; - -class Date { - static Table memtbl; - mutable bool cache_valid; -public: - mutable char* cache; - void compute_cache_value() const; -}; - +enum Type { S, I }; + +struct Entry { + char* name; + Type t; + char* s; + int i; +private: + int internal; +}; + +class Name { + const char* s; +}; + +class Table { + Name* p; + int sz; +public: + Table(int s=15) { p = new Name[sz=s]; } // constructor + ~Table() { delete[] p; } + Name* lookup (const char*); + bool insert(Name*); +}; + +class Date { + static Table memtbl; + mutable bool cache_valid; +public: + mutable char* cache; + void compute_cache_value() const; +}; + diff --git a/cpp/ql/test/library-tests/files/files1.cpp b/cpp/ql/test/library-tests/files/files1.cpp index cd30b0b78ba..210c5586e7a 100644 --- a/cpp/ql/test/library-tests/files/files1.cpp +++ b/cpp/ql/test/library-tests/files/files1.cpp @@ -1,9 +1,9 @@ -#include "files1.h" - - -void swap(int* p, int* q) -{ - int t = *p; - *p = *q; - *q = t; -} +#include "files1.h" + + +void swap(int* p, int* q) +{ + int t = *p; + *p = *q; + *q = t; +} diff --git a/cpp/ql/test/library-tests/files/files1.h b/cpp/ql/test/library-tests/files/files1.h index 90b150ae9d6..af92b2bded3 100644 --- a/cpp/ql/test/library-tests/files/files1.h +++ b/cpp/ql/test/library-tests/files/files1.h @@ -1,2 +1,2 @@ - -extern void swap(int*, int*); + +extern void swap(int*, int*); diff --git a/cpp/ql/test/library-tests/files/files2.cpp b/cpp/ql/test/library-tests/files/files2.cpp index 301b082a534..6dd7ec111ee 100644 --- a/cpp/ql/test/library-tests/files/files2.cpp +++ b/cpp/ql/test/library-tests/files/files2.cpp @@ -1,7 +1,7 @@ -#include "files1.h" - -void g() { - int x = 2; - int y = 4; - swap(&x,&y); -} +#include "files1.h" + +void g() { + int x = 2; + int y = 4; + swap(&x,&y); +} diff --git a/cpp/ql/test/library-tests/functions/functions/functions.cpp b/cpp/ql/test/library-tests/functions/functions/functions.cpp index f3c630cebbb..18b4f6ee5e2 100644 --- a/cpp/ql/test/library-tests/functions/functions/functions.cpp +++ b/cpp/ql/test/library-tests/functions/functions/functions.cpp @@ -1,33 +1,33 @@ -void f(int a, int b) { - bool c = a==b; -} - -void g(); - -struct A { - void af() { - - } - void ag(); -}; - -void g() { - A a; - a.ag(); -} - -class Name { - const char* s; -}; - -class Table { - Name* p; - int sz; -public: - Table(int s=15) { p = new Name[sz=s]; } // constructor - ~Table() { delete[] p; } - Name* lookup (const char*); - bool insert(Name*); -}; - - +void f(int a, int b) { + bool c = a==b; +} + +void g(); + +struct A { + void af() { + + } + void ag(); +}; + +void g() { + A a; + a.ag(); +} + +class Name { + const char* s; +}; + +class Table { + Name* p; + int sz; +public: + Table(int s=15) { p = new Name[sz=s]; } // constructor + ~Table() { delete[] p; } + Name* lookup (const char*); + bool insert(Name*); +}; + + diff --git a/cpp/ql/test/library-tests/ir/constant_func/constant_func.cpp b/cpp/ql/test/library-tests/ir/constant_func/constant_func.cpp index 9a176b82b61..107d79da46b 100644 --- a/cpp/ql/test/library-tests/ir/constant_func/constant_func.cpp +++ b/cpp/ql/test/library-tests/ir/constant_func/constant_func.cpp @@ -1,32 +1,32 @@ -int ReturnConstant() { - return 7; -} - -int ReturnConstantPhi(bool b) { - if (b) { - return 7; - } - else { - return 7; - } -} - -int GetInt(); - -int ReturnNonConstantPhi(bool b) { - if (b) { - return 7; - } - else { - return GetInt(); - } -} - -int ReturnConstantPhiLoop(int x) { - int y = 7; - while (x > 0) { - y = 7; - --x; - } - return y; -} +int ReturnConstant() { + return 7; +} + +int ReturnConstantPhi(bool b) { + if (b) { + return 7; + } + else { + return 7; + } +} + +int GetInt(); + +int ReturnNonConstantPhi(bool b) { + if (b) { + return 7; + } + else { + return GetInt(); + } +} + +int ReturnConstantPhiLoop(int x) { + int y = 7; + while (x > 0) { + y = 7; + --x; + } + return y; +} diff --git a/cpp/ql/test/library-tests/ir/escape/escape.cpp b/cpp/ql/test/library-tests/ir/escape/escape.cpp index 81a23ac4fb2..8a3e57a25d2 100644 --- a/cpp/ql/test/library-tests/ir/escape/escape.cpp +++ b/cpp/ql/test/library-tests/ir/escape/escape.cpp @@ -1,98 +1,98 @@ -void CallByPointer(int* p); -void CallByReference(int& r); - -struct Point { - float x; - float y; - float z; -}; - -struct Base { - float b; -}; - -struct ReusedBase { - float rb; -}; - -struct Intermediate1 : Base, ReusedBase { - float i1; -}; - -struct Intermediate2 : ReusedBase { - float i2; -}; - -struct Derived : Intermediate1, Intermediate2 { - float d; -}; - -void Escape() -{ - int no_result; - int no_; - - no_ = 1; - no_ = no_; - no_result = no_; - no_result = *&no_; -// no_result = (int&)no_; Restore when we have correct IR types for glvalues - no_; - &no_; - no_result = *((&no_) + 0); - no_result = *((&no_) - 0); - no_result = *(0 + &no_); - if (&no_) { - } - while (&no_) { - } - do { - } while (&no_); - for(&no_; &no_; &no_) { - } - - if (&no_ == nullptr) { - } - while (&no_ != nullptr) { - } - - int no_Array[10]; - no_Array; - (int*)no_Array; - no_Array[5]; - 5[no_Array]; - no_result = no_Array[5]; - no_result = 5[no_Array]; - - Point no_Point = { 1, 2, 3 }; - float no_x = no_Point.x; - no_Point.y = no_x; - float no_y = (&no_Point)->y; - (&no_Point)->y = no_y; - float no_z = *(&no_Point.z); - *(&no_Point.z) = no_z; - - Derived no_Derived; - no_Derived.b = 0; - float no_b = no_Derived.b; - no_Derived.i2 = 1; - float no_i2 = no_Derived.i2; - - int no_ssa_addrOf; - int* no_p = &no_ssa_addrOf; - - int no_ssa_refTo; - int& no_r = no_ssa_refTo; - - int no_ssa_refToArrayElement[10]; - int& no_rae = no_ssa_refToArrayElement[5]; - - int no_ssa_refToArray[10]; - int (&no_ra)[10] = no_ssa_refToArray; - - int passByPtr; - CallByPointer(&passByPtr); - - int passByRef; - CallByReference(passByRef); -} +void CallByPointer(int* p); +void CallByReference(int& r); + +struct Point { + float x; + float y; + float z; +}; + +struct Base { + float b; +}; + +struct ReusedBase { + float rb; +}; + +struct Intermediate1 : Base, ReusedBase { + float i1; +}; + +struct Intermediate2 : ReusedBase { + float i2; +}; + +struct Derived : Intermediate1, Intermediate2 { + float d; +}; + +void Escape() +{ + int no_result; + int no_; + + no_ = 1; + no_ = no_; + no_result = no_; + no_result = *&no_; +// no_result = (int&)no_; Restore when we have correct IR types for glvalues + no_; + &no_; + no_result = *((&no_) + 0); + no_result = *((&no_) - 0); + no_result = *(0 + &no_); + if (&no_) { + } + while (&no_) { + } + do { + } while (&no_); + for(&no_; &no_; &no_) { + } + + if (&no_ == nullptr) { + } + while (&no_ != nullptr) { + } + + int no_Array[10]; + no_Array; + (int*)no_Array; + no_Array[5]; + 5[no_Array]; + no_result = no_Array[5]; + no_result = 5[no_Array]; + + Point no_Point = { 1, 2, 3 }; + float no_x = no_Point.x; + no_Point.y = no_x; + float no_y = (&no_Point)->y; + (&no_Point)->y = no_y; + float no_z = *(&no_Point.z); + *(&no_Point.z) = no_z; + + Derived no_Derived; + no_Derived.b = 0; + float no_b = no_Derived.b; + no_Derived.i2 = 1; + float no_i2 = no_Derived.i2; + + int no_ssa_addrOf; + int* no_p = &no_ssa_addrOf; + + int no_ssa_refTo; + int& no_r = no_ssa_refTo; + + int no_ssa_refToArrayElement[10]; + int& no_rae = no_ssa_refToArrayElement[5]; + + int no_ssa_refToArray[10]; + int (&no_ra)[10] = no_ssa_refToArray; + + int passByPtr; + CallByPointer(&passByPtr); + + int passByRef; + CallByReference(passByRef); +} diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index a7da38c6d97..884abe554a6 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -6303,3 +6303,35 @@ ir.cpp: # 958| Type = int # 958| ValueCategory = prvalue(load) # 959| 8: return ... +# 961| designatedInit() -> int +# 961| params: +# 961| body: { ... } +# 962| 0: declaration +# 962| 0: definition of a1 +# 962| Type = int[1000] +# 962| init: initializer for a1 +# 962| expr: {...} +# 962| Type = int[1000] +# 962| ValueCategory = prvalue +# 962| 0: 10002 +# 962| Type = int +# 962| Value = 10002 +# 962| ValueCategory = prvalue +# 962| 1: 10900 +# 962| Type = int +# 962| Value = 10900 +# 962| ValueCategory = prvalue +# 963| 1: return ... +# 963| 0: access to array +# 963| Type = int +# 963| ValueCategory = prvalue(load) +# 963| 0: array to pointer conversion +# 963| Type = int * +# 963| ValueCategory = prvalue +# 963| expr: a1 +# 963| Type = int[1000] +# 963| ValueCategory = lvalue +# 963| 1: 900 +# 963| Type = int +# 963| Value = 900 +# 963| ValueCategory = prvalue diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_ir.expected index b9a7b4f2403..5fbbec2afb7 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_ir.expected @@ -3906,3 +3906,49 @@ ir.cpp: # 950| v0_65(void) = ReturnVoid : # 950| v0_66(void) = UnmodeledUse : mu* # 950| v0_67(void) = ExitFunction : + +# 961| designatedInit() -> int +# 961| Block 0 +# 961| v0_0(void) = EnterFunction : +# 961| mu0_1(unknown) = UnmodeledDefinition : +# 962| r0_2(glval) = VariableAddress[a1] : +# 962| r0_3(int) = Constant[0] : +# 962| r0_4(glval) = PointerAdd : r0_2, r0_3 +# 962| r0_5(unknown[8]) = Constant[0] : +# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5 +#-----| Goto -> Block 2 + +# 962| Block 1 +# 962| r1_0(int) = Constant[900] : +# 962| r1_1(glval) = PointerAdd : r0_2, r1_0 +# 962| r1_2(int) = Constant[10900] : +# 962| mu1_3(int) = Store : r1_1, r1_2 +# 962| r1_4(int) = Constant[901] : +# 962| r1_5(glval) = PointerAdd : r0_2, r1_4 +# 962| r1_6(unknown[396]) = Constant[0] : +# 962| mu1_7(unknown[396]) = Store : r1_5, r1_6 +#-----| Goto -> Block 2 + +# 963| Block 2 +# 963| r2_0(glval) = VariableAddress[#return] : +# 963| r2_1(glval) = VariableAddress[a1] : +# 963| r2_2(int *) = Convert : r2_1 +# 963| r2_3(int) = Constant[900] : +# 963| r2_4(int *) = PointerAdd[4] : r2_2, r2_3 +# 963| r2_5(int) = Load : r2_4, mu0_1 +# 963| m2_6(int) = Store : r2_0, r2_5 +# 961| r2_7(glval) = VariableAddress[#return] : +# 961| v2_8(void) = ReturnValue : r2_7, m2_6 +# 961| v2_9(void) = UnmodeledUse : mu* +# 961| v2_10(void) = ExitFunction : + +# 962| Block 3 +# 962| r3_0(int) = Constant[2] : +# 962| r3_1(glval) = PointerAdd : r0_2, r3_0 +# 962| r3_2(int) = Constant[10002] : +# 962| mu3_3(int) = Store : r3_1, r3_2 +# 962| r3_4(int) = Constant[3] : +# 962| r3_5(glval) = PointerAdd : r0_2, r3_4 +# 962| r3_6(unknown[3588]) = Constant[0] : +# 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6 +#-----| Goto -> Block 2 diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp index 05682c61db2..3ff4c53c17e 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -1,979 +1,984 @@ -void Constants() { - char c_i = 1; - char c_c = 'A'; - - signed char sc_i = -1; - signed char sc_c = 'A'; - - unsigned char uc_i = 5; - unsigned char uc_c = 'A'; - - short s = 5; - unsigned short us = 5; - - int i = 5; - unsigned int ui = 5; - - long l = 5; - unsigned long ul = 5; - - long long ll_i = 5; - long long ll_ll = 5LL; - unsigned long long ull_i = 5; - unsigned long long ull_ull = 5ULL; - - bool b_t = true; - bool b_f = false; - - wchar_t wc_i = 5; - wchar_t wc_c = L'A'; - - char16_t c16 = u'A'; - char32_t c32 = U'A'; - - float f_i = 1; - float f_f = 1.0f; - float f_d = 1.0; - - double d_i = 1; - double d_f = 1.0f; - double d_d = 1.0; -} - -void Foo() { - int x = 5 + 12; - short y = 7; - y = x + y; - x = x * y; -} - -void IntegerOps(int x, int y) { - int z; - - z = x + y; - z = x - y; - z = x * y; - z = x / y; - z = x % y; - - z = x & y; - z = x | y; - z = x ^ y; - - z = x << y; - z = x >> y; - - z = x; - - z += x; - z -= x; - z *= x; - z /= x; - z %= x; - - z &= x; - z |= x; - z ^= x; - - z <<= x; - z >>= x; - - z = +x; - z = -x; - z = ~x; - z = !x; -} - -void IntegerCompare(int x, int y) { - bool b; - - b = x == y; - b = x != y; - b = x < y; - b = x > y; - b = x <= y; - b = x >= y; -} - -void IntegerCrement(int x) { - int y; - - y = ++x; - y = --x; - y = x++; - y = x--; -} - -void IntegerCrement_LValue(int x) { - int* p; - - p = &(++x); - p = &(--x); -} - -void FloatOps(double x, double y) { - double z; - - z = x + y; - z = x - y; - z = x * y; - z = x / y; - - z = x; - - z += x; - z -= x; - z *= x; - z /= x; - - z = +x; - z = -x; -} - -void FloatCompare(double x, double y) { - bool b; - - b = x == y; - b = x != y; - b = x < y; - b = x > y; - b = x <= y; - b = x >= y; -} - -void FloatCrement(float x) { - float y; - - y = ++x; - y = --x; - y = x++; - y = x--; -} - -void PointerOps(int* p, int i) { - int* q; - bool b; - - q = p + i; - q = i + p; - q = p - i; - i = p - q; - - q = p; - - q += i; - q -= i; - - b = p; - b = !p; -} - -void ArrayAccess(int* p, int i) { - int x; - - x = p[i]; - x = i[p]; - - p[i] = x; - i[p] = x; - - int a[10]; - x = a[i]; - x = i[a]; - a[i] = x; - i[a] = x; -} - -void StringLiteral(int i) { - char c = "Foo"[i]; - wchar_t* pwc = L"Bar"; - wchar_t wc = pwc[i]; -} - -void PointerCompare(int* p, int* q) { - bool b; - - b = p == q; - b = p != q; - b = p < q; - b = p > q; - b = p <= q; - b = p >= q; -} - -void PointerCrement(int* p) { - int* q; - - q = ++p; - q = --p; - q = p++; - q = p--; -} - -void CompoundAssignment() { - // No conversion necessary - int x = 5; - x += 7; - - // Left side is converted to 'int' - short y = 5; - y += x; - - // Technically the left side is promoted to int, but we don't model that - y <<= 1; - - // Left side is converted to 'float' - long z = 7; - z += 2.0f; -} - -void UninitializedVariables() { - int x; - int y = x; -} - -int Parameters(int x, int y) { - return x % y; -} - -void IfStatements(bool b, int x, int y) { - if (b) { - } - - if (b) { - x = y; - } - - if (x < 7) - x = 2; - else - x = 7; -} - -void WhileStatements(int n) { - while (n > 0) { - n -= 1; - } -} - -void DoStatements(int n) { - do { - n -= 1; - } while (n > 0); -} - -void For_Empty() { - int j; - for (;;) { - ; - } -} - -void For_Init() { - for (int i = 0;;) { - ; - } -} - -void For_Condition() { - int i = 0; - for (; i < 10;) { - ; - } -} - -void For_Update() { - int i = 0; - for (;; i += 1) { - ; - } -} - -void For_InitCondition() { - for (int i = 0; i < 10;) { - ; - } -} - -void For_InitUpdate() { - for (int i = 0;; i += 1) { - ; - } -} - -void For_ConditionUpdate() { - int i = 0; - for (; i < 10; i += 1) { - ; - } -} - -void For_InitConditionUpdate() { - for (int i = 0; i < 10; i += 1) { - ; - } -} - -void For_Break() { - for (int i = 0; i < 10; i += 1) { - if (i == 5) { - break; - } - } -} - -void For_Continue_Update() { - for (int i = 0; i < 10; i += 1) { - if (i == 5) { - continue; - } - } -} - -void For_Continue_NoUpdate() { - for (int i = 0; i < 10;) { - if (i == 5) { - continue; - } - } -} - -int Dereference(int* p) { - *p = 1; - return *p; -} - -int g; - -int* AddressOf() { - return &g; -} - -void Break(int n) { - while (n > 0) { - if (n == 1) - break; - n -= 1; - } -} - -void Continue(int n) { - do { - if (n == 1) { - continue; - } - n -= 1; - } while (n > 0); -} - -void VoidFunc(); -int Add(int x, int y); - -void Call() { - VoidFunc(); -} - -int CallAdd(int x, int y) { - return Add(x, y); -} - -int Comma(int x, int y) { - return VoidFunc(), CallAdd(x, y); -} - -void Switch(int x) { - int y; - switch (x) { - y = 1234; - - case -1: - y = -1; - break; - - case 1: - case 2: - y = 1; - break; - - case 3: - y = 3; - case 4: - y = 4; - break; - - default: - y = 0; - break; - - y = 5678; - } -} - -struct Point { - int x; - int y; -}; - -struct Rect { - Point topLeft; - Point bottomRight; -}; - -Point ReturnStruct(Point pt) { - return pt; -} - -void FieldAccess() { - Point pt; - pt.x = 5; - pt.y = pt.x; - int* p = &pt.y; -} - -void LogicalOr(bool a, bool b) { - int x; - if (a || b) { - x = 7; - } - - if (a || b) { - x = 1; - } - else { - x = 5; - } -} - -void LogicalAnd(bool a, bool b) { - int x; - if (a && b) { - x = 7; - } - - if (a && b) { - x = 1; - } - else { - x = 5; - } -} - -void LogicalNot(bool a, bool b) { - int x; - if (!a) { - x = 1; - } - - if (!(a && b)) { - x = 2; - } - else { - x = 3; - } -} - -void ConditionValues(bool a, bool b) { - bool x; - x = a && b; - x = a || b; - x = !(a || b); -} - -void Conditional(bool a, int x, int y) { - int z = a ? x : y; -} - -void Conditional_LValue(bool a) { - int x; - int y; - (a ? x : y) = 5; -} - -void Conditional_Void(bool a) { - a ? VoidFunc() : VoidFunc(); -} - -void Nullptr() { - int* p = nullptr; - int* q = 0; - p = nullptr; - q = 0; -} - -void InitList(int x, float f) { - Point pt1 = { x, f }; - Point pt2 = { x }; - Point pt3 = {}; - - int x1 = { 1 }; - int x2 = {}; -} - -void NestedInitList(int x, float f) { - Rect r1 = {}; - Rect r2 = { { x, f } }; - Rect r3 = { { x, f }, { x, f } }; - Rect r4 = { { x }, { x } }; -} - -void ArrayInit(int x, float f) { - int a1[3] = {}; - int a2[3] = { x, f, 0 }; - int a3[3] = { x }; -} - -union U { - double d; - int i; -}; - -void UnionInit(int x, float f) { - U u1 = { f }; -// U u2 = {}; Waiting for fix -} - -void EarlyReturn(int x, int y) { - if (x < y) { - return; - } - - y = x; -} - -int EarlyReturnValue(int x, int y) { - if (x < y) { - return x; - } - - return x + y; -} - -int CallViaFuncPtr(int (*pfn)(int)) { - return pfn(5); -} - -typedef enum { - E_0, - E_1 -} E; - -int EnumSwitch(E e) { - switch (e) { - case E_0: - return 0; - case E_1: - return 1; - default: - return -1; - } -} - -void InitArray() { - char a_pad[32] = ""; - char a_nopad[4] = "foo"; - char a_infer[] = "blah"; - char b[2]; - char c[2] = {}; - char d[2] = { 0 }; - char e[2] = { 0, 1 }; - char f[3] = { 0 }; -} - -void VarArgFunction(const char* s, ...); - -void VarArgs() { - VarArgFunction("%d %s", 1, "string"); -} - -int FuncPtrTarget(int); - -void SetFuncPtr() { - int (*pfn)(int) = FuncPtrTarget; - pfn = &FuncPtrTarget; - pfn = *FuncPtrTarget; - pfn = ***&FuncPtrTarget; -} - -struct String { - String(); - String(const String&); - String(String&&); - String(const char*); - ~String(); - - String& operator=(const String&); - String& operator=(String&&); - - const char* c_str() const; - -private: - const char* p; -}; - -String ReturnObject(); - -void DeclareObject() { - String s1; - String s2("hello"); - String s3 = ReturnObject(); - String s4 = String("test"); -} - -void CallMethods(String& r, String* p, String s) { - r.c_str(); - p->c_str(); - s.c_str(); -} - -class C { -public: - static int StaticMemberFunction(int x) { - return x; - } - - int InstanceMemberFunction(int x) { - return x; - } - - virtual int VirtualMemberFunction(int x) { - return x; - } - - void FieldAccess() { - this->m_a = 0; - (*this).m_a = 1; - m_a = 2; - int x; - x = this->m_a; - x = (*this).m_a; - x = m_a; - } - - void MethodCalls() { - this->InstanceMemberFunction(0); - (*this).InstanceMemberFunction(1); - InstanceMemberFunction(2); - } - - C() : - m_a(1), - m_c(3), - m_e{}, - m_f("test") - { - } - -private: - int m_a; - String m_b; - char m_c; - float m_d; - void* m_e; - String m_f; -}; - -int DerefReference(int& r) { - return r; -} - -int& TakeReference() { - return g; -} - -String& ReturnReference(); - -void InitReference(int x) { - int& r = x; - int& r2 = r; - const String& r3 = ReturnReference(); -} - -void ArrayReferences() { - int a[10]; - int (&ra)[10] = a; - int x = ra[5]; -} - -void FunctionReferences() { - int(&rfn)(int) = FuncPtrTarget; - int(*pfn)(int) = rfn; - rfn(5); -} - -template -T min(T x, T y) { - return (x < y) ? x : y; -} - -int CallMin(int x, int y) { - return min(x, y); -} - -template -struct Outer { - template - static T Func(U x, V y) { - return T(); - } -}; - -double CallNestedTemplateFunc() { - return Outer::Func(nullptr, 'o'); -} - -void TryCatch(bool b) { - try { - int x = 5; - if (b) { - throw "string literal"; - } - else if (x < 2) { - x = b ? 7 : throw String("String object"); - } - x = 7; - } - catch (const char* s) { - throw String(s); - } - catch (const String& e) { - } - catch (...) { - throw; - } -} - -struct Base { - String base_s; - - Base() { - } - ~Base() { - } -}; - -struct Middle : Base { - String middle_s; - - Middle() { - } - ~Middle() { - } -}; - -struct Derived : Middle { - String derived_s; - - Derived() { - } - ~Derived() { - } -}; - -struct MiddleVB1 : virtual Base { - String middlevb1_s; - - MiddleVB1() { - } - ~MiddleVB1() { - } -}; - -struct MiddleVB2 : virtual Base { - String middlevb2_s; - - MiddleVB2() { - } - ~MiddleVB2() { - } -}; - -struct DerivedVB : MiddleVB1, MiddleVB2 { - String derivedvb_s; - - DerivedVB() { - } - ~DerivedVB() { - } -}; - -void HierarchyConversions() { - Base b; - Middle m; - Derived d; - - Base* pb = &b; - Middle* pm = &m; - Derived* pd = &d; - - b = m; - b = (Base)m; - b = static_cast(m); - pb = pm; - pb = (Base*)pm; - pb = static_cast(pm); - pb = reinterpret_cast(pm); - - m = (Middle&)b; - m = static_cast(b); - pm = (Middle*)pb; - pm = static_cast(pb); - pm = reinterpret_cast(pb); - - b = d; - b = (Base)d; - b = static_cast(d); - pb = pd; - pb = (Base*)pd; - pb = static_cast(pd); - pb = reinterpret_cast(pd); - - d = (Derived&)b; - d = static_cast(b); - pd = (Derived*)pb; - pd = static_cast(pb); - pd = reinterpret_cast(pb); - - MiddleVB1* pmv = nullptr; - DerivedVB* pdv = nullptr; - pb = pmv; - pb = pdv; -} - -struct PolymorphicBase { - virtual ~PolymorphicBase(); -}; - -struct PolymorphicDerived : PolymorphicBase { -}; - -void DynamicCast() { - PolymorphicBase b; - PolymorphicDerived d; - - PolymorphicBase* pb = &b; - PolymorphicDerived* pd = &d; - - // These two casts are represented as BaseClassCasts because they can be resolved at compile time. - pb = dynamic_cast(pd); - PolymorphicBase& rb = dynamic_cast(d); - - pd = dynamic_cast(pb); - PolymorphicDerived& rd = dynamic_cast(b); - - void* pv = dynamic_cast(pb); - const void* pcv = dynamic_cast(pd); -} - -String::String() : - String("") { // Delegating constructor call -} - -void ArrayConversions() { - char a[5]; - const char* p = a; - p = "test"; - p = &a[0]; - p = &"test"[0]; - char (&ra)[5] = a; - const char (&rs)[5] = "test"; - const char (*pa)[5] = &a; - pa = &"test"; -} - -void FuncPtrConversions(int(*pfn)(int), void* p) { - p = (void*)pfn; - pfn = (int(*)(int))p; -} - -void VarArgUsage(int x, ...) { - __builtin_va_list args; - - __builtin_va_start(args, x); - __builtin_va_list args2; - __builtin_va_start(args2, args); - double d = __builtin_va_arg(args, double); - float f = __builtin_va_arg(args, float); - __builtin_va_end(args); - __builtin_va_end(args2); -} - -void CastToVoid(int x) { - (void)x; -} - -void ConstantConditions(int x) { - bool a = true && true; - int b = (true) ? x : x; -} - -typedef unsigned long size_t; - -namespace std { - enum class align_val_t : size_t {}; -} - -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 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); - -struct SizedDealloc { - char a[32]; - void* operator new(size_t); - void* operator new[](size_t); - void operator delete(void*, size_t); - void operator delete[](void*, size_t); -}; - -struct alignas(128) Overaligned { - char a[256]; -}; - -struct DefaultCtorWithDefaultParam { - DefaultCtorWithDefaultParam(double d = 1.0); -}; - -void OperatorNew() { - new int; // No constructor - new(1.0f) int; // Placement new, no constructor - new int(); // Zero-init - new String(); // Constructor - new(1.0f) String("hello"); // Placement new, constructor with args - new Overaligned; // Aligned new - new(1.0f) Overaligned(); // Placement aligned new with zero-init -} - -void OperatorNewArray(int n) { - new int[10]; // Constant size - new int[n]; // No constructor - new(1.0f) int[n]; // Placement new, no constructor - new String[n]; // Constructor - new Overaligned[n]; // Aligned new - new(1.0f) Overaligned[10]; // Aligned placement new - new DefaultCtorWithDefaultParam[n]; - new int[n] { 0, 1, 2 }; -} - -#if 0 -void OperatorDelete() { - delete static_cast(nullptr); // No destructor - delete static_cast(nullptr); // Non-virtual destructor, with size. - delete static_cast(nullptr); // No destructor, with size. - delete static_cast(nullptr); // No destructor, with size and alignment. - delete static_cast(nullptr); // Virtual destructor -} - -void OperatorDeleteArray() { - delete[] static_cast(nullptr); // No destructor - delete[] static_cast(nullptr); // Non-virtual destructor, with size. - delete[] static_cast(nullptr); // No destructor, with size. - delete[] static_cast(nullptr); // No destructor, with size and alignment. - delete[] static_cast(nullptr); // Virtual destructor -} -#endif - -// semmle-extractor-options: -std=c++17 +void Constants() { + char c_i = 1; + char c_c = 'A'; + + signed char sc_i = -1; + signed char sc_c = 'A'; + + unsigned char uc_i = 5; + unsigned char uc_c = 'A'; + + short s = 5; + unsigned short us = 5; + + int i = 5; + unsigned int ui = 5; + + long l = 5; + unsigned long ul = 5; + + long long ll_i = 5; + long long ll_ll = 5LL; + unsigned long long ull_i = 5; + unsigned long long ull_ull = 5ULL; + + bool b_t = true; + bool b_f = false; + + wchar_t wc_i = 5; + wchar_t wc_c = L'A'; + + char16_t c16 = u'A'; + char32_t c32 = U'A'; + + float f_i = 1; + float f_f = 1.0f; + float f_d = 1.0; + + double d_i = 1; + double d_f = 1.0f; + double d_d = 1.0; +} + +void Foo() { + int x = 5 + 12; + short y = 7; + y = x + y; + x = x * y; +} + +void IntegerOps(int x, int y) { + int z; + + z = x + y; + z = x - y; + z = x * y; + z = x / y; + z = x % y; + + z = x & y; + z = x | y; + z = x ^ y; + + z = x << y; + z = x >> y; + + z = x; + + z += x; + z -= x; + z *= x; + z /= x; + z %= x; + + z &= x; + z |= x; + z ^= x; + + z <<= x; + z >>= x; + + z = +x; + z = -x; + z = ~x; + z = !x; +} + +void IntegerCompare(int x, int y) { + bool b; + + b = x == y; + b = x != y; + b = x < y; + b = x > y; + b = x <= y; + b = x >= y; +} + +void IntegerCrement(int x) { + int y; + + y = ++x; + y = --x; + y = x++; + y = x--; +} + +void IntegerCrement_LValue(int x) { + int* p; + + p = &(++x); + p = &(--x); +} + +void FloatOps(double x, double y) { + double z; + + z = x + y; + z = x - y; + z = x * y; + z = x / y; + + z = x; + + z += x; + z -= x; + z *= x; + z /= x; + + z = +x; + z = -x; +} + +void FloatCompare(double x, double y) { + bool b; + + b = x == y; + b = x != y; + b = x < y; + b = x > y; + b = x <= y; + b = x >= y; +} + +void FloatCrement(float x) { + float y; + + y = ++x; + y = --x; + y = x++; + y = x--; +} + +void PointerOps(int* p, int i) { + int* q; + bool b; + + q = p + i; + q = i + p; + q = p - i; + i = p - q; + + q = p; + + q += i; + q -= i; + + b = p; + b = !p; +} + +void ArrayAccess(int* p, int i) { + int x; + + x = p[i]; + x = i[p]; + + p[i] = x; + i[p] = x; + + int a[10]; + x = a[i]; + x = i[a]; + a[i] = x; + i[a] = x; +} + +void StringLiteral(int i) { + char c = "Foo"[i]; + wchar_t* pwc = L"Bar"; + wchar_t wc = pwc[i]; +} + +void PointerCompare(int* p, int* q) { + bool b; + + b = p == q; + b = p != q; + b = p < q; + b = p > q; + b = p <= q; + b = p >= q; +} + +void PointerCrement(int* p) { + int* q; + + q = ++p; + q = --p; + q = p++; + q = p--; +} + +void CompoundAssignment() { + // No conversion necessary + int x = 5; + x += 7; + + // Left side is converted to 'int' + short y = 5; + y += x; + + // Technically the left side is promoted to int, but we don't model that + y <<= 1; + + // Left side is converted to 'float' + long z = 7; + z += 2.0f; +} + +void UninitializedVariables() { + int x; + int y = x; +} + +int Parameters(int x, int y) { + return x % y; +} + +void IfStatements(bool b, int x, int y) { + if (b) { + } + + if (b) { + x = y; + } + + if (x < 7) + x = 2; + else + x = 7; +} + +void WhileStatements(int n) { + while (n > 0) { + n -= 1; + } +} + +void DoStatements(int n) { + do { + n -= 1; + } while (n > 0); +} + +void For_Empty() { + int j; + for (;;) { + ; + } +} + +void For_Init() { + for (int i = 0;;) { + ; + } +} + +void For_Condition() { + int i = 0; + for (; i < 10;) { + ; + } +} + +void For_Update() { + int i = 0; + for (;; i += 1) { + ; + } +} + +void For_InitCondition() { + for (int i = 0; i < 10;) { + ; + } +} + +void For_InitUpdate() { + for (int i = 0;; i += 1) { + ; + } +} + +void For_ConditionUpdate() { + int i = 0; + for (; i < 10; i += 1) { + ; + } +} + +void For_InitConditionUpdate() { + for (int i = 0; i < 10; i += 1) { + ; + } +} + +void For_Break() { + for (int i = 0; i < 10; i += 1) { + if (i == 5) { + break; + } + } +} + +void For_Continue_Update() { + for (int i = 0; i < 10; i += 1) { + if (i == 5) { + continue; + } + } +} + +void For_Continue_NoUpdate() { + for (int i = 0; i < 10;) { + if (i == 5) { + continue; + } + } +} + +int Dereference(int* p) { + *p = 1; + return *p; +} + +int g; + +int* AddressOf() { + return &g; +} + +void Break(int n) { + while (n > 0) { + if (n == 1) + break; + n -= 1; + } +} + +void Continue(int n) { + do { + if (n == 1) { + continue; + } + n -= 1; + } while (n > 0); +} + +void VoidFunc(); +int Add(int x, int y); + +void Call() { + VoidFunc(); +} + +int CallAdd(int x, int y) { + return Add(x, y); +} + +int Comma(int x, int y) { + return VoidFunc(), CallAdd(x, y); +} + +void Switch(int x) { + int y; + switch (x) { + y = 1234; + + case -1: + y = -1; + break; + + case 1: + case 2: + y = 1; + break; + + case 3: + y = 3; + case 4: + y = 4; + break; + + default: + y = 0; + break; + + y = 5678; + } +} + +struct Point { + int x; + int y; +}; + +struct Rect { + Point topLeft; + Point bottomRight; +}; + +Point ReturnStruct(Point pt) { + return pt; +} + +void FieldAccess() { + Point pt; + pt.x = 5; + pt.y = pt.x; + int* p = &pt.y; +} + +void LogicalOr(bool a, bool b) { + int x; + if (a || b) { + x = 7; + } + + if (a || b) { + x = 1; + } + else { + x = 5; + } +} + +void LogicalAnd(bool a, bool b) { + int x; + if (a && b) { + x = 7; + } + + if (a && b) { + x = 1; + } + else { + x = 5; + } +} + +void LogicalNot(bool a, bool b) { + int x; + if (!a) { + x = 1; + } + + if (!(a && b)) { + x = 2; + } + else { + x = 3; + } +} + +void ConditionValues(bool a, bool b) { + bool x; + x = a && b; + x = a || b; + x = !(a || b); +} + +void Conditional(bool a, int x, int y) { + int z = a ? x : y; +} + +void Conditional_LValue(bool a) { + int x; + int y; + (a ? x : y) = 5; +} + +void Conditional_Void(bool a) { + a ? VoidFunc() : VoidFunc(); +} + +void Nullptr() { + int* p = nullptr; + int* q = 0; + p = nullptr; + q = 0; +} + +void InitList(int x, float f) { + Point pt1 = { x, f }; + Point pt2 = { x }; + Point pt3 = {}; + + int x1 = { 1 }; + int x2 = {}; +} + +void NestedInitList(int x, float f) { + Rect r1 = {}; + Rect r2 = { { x, f } }; + Rect r3 = { { x, f }, { x, f } }; + Rect r4 = { { x }, { x } }; +} + +void ArrayInit(int x, float f) { + int a1[3] = {}; + int a2[3] = { x, f, 0 }; + int a3[3] = { x }; +} + +union U { + double d; + int i; +}; + +void UnionInit(int x, float f) { + U u1 = { f }; +// U u2 = {}; Waiting for fix +} + +void EarlyReturn(int x, int y) { + if (x < y) { + return; + } + + y = x; +} + +int EarlyReturnValue(int x, int y) { + if (x < y) { + return x; + } + + return x + y; +} + +int CallViaFuncPtr(int (*pfn)(int)) { + return pfn(5); +} + +typedef enum { + E_0, + E_1 +} E; + +int EnumSwitch(E e) { + switch (e) { + case E_0: + return 0; + case E_1: + return 1; + default: + return -1; + } +} + +void InitArray() { + char a_pad[32] = ""; + char a_nopad[4] = "foo"; + char a_infer[] = "blah"; + char b[2]; + char c[2] = {}; + char d[2] = { 0 }; + char e[2] = { 0, 1 }; + char f[3] = { 0 }; +} + +void VarArgFunction(const char* s, ...); + +void VarArgs() { + VarArgFunction("%d %s", 1, "string"); +} + +int FuncPtrTarget(int); + +void SetFuncPtr() { + int (*pfn)(int) = FuncPtrTarget; + pfn = &FuncPtrTarget; + pfn = *FuncPtrTarget; + pfn = ***&FuncPtrTarget; +} + +struct String { + String(); + String(const String&); + String(String&&); + String(const char*); + ~String(); + + String& operator=(const String&); + String& operator=(String&&); + + const char* c_str() const; + +private: + const char* p; +}; + +String ReturnObject(); + +void DeclareObject() { + String s1; + String s2("hello"); + String s3 = ReturnObject(); + String s4 = String("test"); +} + +void CallMethods(String& r, String* p, String s) { + r.c_str(); + p->c_str(); + s.c_str(); +} + +class C { +public: + static int StaticMemberFunction(int x) { + return x; + } + + int InstanceMemberFunction(int x) { + return x; + } + + virtual int VirtualMemberFunction(int x) { + return x; + } + + void FieldAccess() { + this->m_a = 0; + (*this).m_a = 1; + m_a = 2; + int x; + x = this->m_a; + x = (*this).m_a; + x = m_a; + } + + void MethodCalls() { + this->InstanceMemberFunction(0); + (*this).InstanceMemberFunction(1); + InstanceMemberFunction(2); + } + + C() : + m_a(1), + m_c(3), + m_e{}, + m_f("test") + { + } + +private: + int m_a; + String m_b; + char m_c; + float m_d; + void* m_e; + String m_f; +}; + +int DerefReference(int& r) { + return r; +} + +int& TakeReference() { + return g; +} + +String& ReturnReference(); + +void InitReference(int x) { + int& r = x; + int& r2 = r; + const String& r3 = ReturnReference(); +} + +void ArrayReferences() { + int a[10]; + int (&ra)[10] = a; + int x = ra[5]; +} + +void FunctionReferences() { + int(&rfn)(int) = FuncPtrTarget; + int(*pfn)(int) = rfn; + rfn(5); +} + +template +T min(T x, T y) { + return (x < y) ? x : y; +} + +int CallMin(int x, int y) { + return min(x, y); +} + +template +struct Outer { + template + static T Func(U x, V y) { + return T(); + } +}; + +double CallNestedTemplateFunc() { + return Outer::Func(nullptr, 'o'); +} + +void TryCatch(bool b) { + try { + int x = 5; + if (b) { + throw "string literal"; + } + else if (x < 2) { + x = b ? 7 : throw String("String object"); + } + x = 7; + } + catch (const char* s) { + throw String(s); + } + catch (const String& e) { + } + catch (...) { + throw; + } +} + +struct Base { + String base_s; + + Base() { + } + ~Base() { + } +}; + +struct Middle : Base { + String middle_s; + + Middle() { + } + ~Middle() { + } +}; + +struct Derived : Middle { + String derived_s; + + Derived() { + } + ~Derived() { + } +}; + +struct MiddleVB1 : virtual Base { + String middlevb1_s; + + MiddleVB1() { + } + ~MiddleVB1() { + } +}; + +struct MiddleVB2 : virtual Base { + String middlevb2_s; + + MiddleVB2() { + } + ~MiddleVB2() { + } +}; + +struct DerivedVB : MiddleVB1, MiddleVB2 { + String derivedvb_s; + + DerivedVB() { + } + ~DerivedVB() { + } +}; + +void HierarchyConversions() { + Base b; + Middle m; + Derived d; + + Base* pb = &b; + Middle* pm = &m; + Derived* pd = &d; + + b = m; + b = (Base)m; + b = static_cast(m); + pb = pm; + pb = (Base*)pm; + pb = static_cast(pm); + pb = reinterpret_cast(pm); + + m = (Middle&)b; + m = static_cast(b); + pm = (Middle*)pb; + pm = static_cast(pb); + pm = reinterpret_cast(pb); + + b = d; + b = (Base)d; + b = static_cast(d); + pb = pd; + pb = (Base*)pd; + pb = static_cast(pd); + pb = reinterpret_cast(pd); + + d = (Derived&)b; + d = static_cast(b); + pd = (Derived*)pb; + pd = static_cast(pb); + pd = reinterpret_cast(pb); + + MiddleVB1* pmv = nullptr; + DerivedVB* pdv = nullptr; + pb = pmv; + pb = pdv; +} + +struct PolymorphicBase { + virtual ~PolymorphicBase(); +}; + +struct PolymorphicDerived : PolymorphicBase { +}; + +void DynamicCast() { + PolymorphicBase b; + PolymorphicDerived d; + + PolymorphicBase* pb = &b; + PolymorphicDerived* pd = &d; + + // These two casts are represented as BaseClassCasts because they can be resolved at compile time. + pb = dynamic_cast(pd); + PolymorphicBase& rb = dynamic_cast(d); + + pd = dynamic_cast(pb); + PolymorphicDerived& rd = dynamic_cast(b); + + void* pv = dynamic_cast(pb); + const void* pcv = dynamic_cast(pd); +} + +String::String() : + String("") { // Delegating constructor call +} + +void ArrayConversions() { + char a[5]; + const char* p = a; + p = "test"; + p = &a[0]; + p = &"test"[0]; + char (&ra)[5] = a; + const char (&rs)[5] = "test"; + const char (*pa)[5] = &a; + pa = &"test"; +} + +void FuncPtrConversions(int(*pfn)(int), void* p) { + p = (void*)pfn; + pfn = (int(*)(int))p; +} + +void VarArgUsage(int x, ...) { + __builtin_va_list args; + + __builtin_va_start(args, x); + __builtin_va_list args2; + __builtin_va_start(args2, args); + double d = __builtin_va_arg(args, double); + float f = __builtin_va_arg(args, float); + __builtin_va_end(args); + __builtin_va_end(args2); +} + +void CastToVoid(int x) { + (void)x; +} + +void ConstantConditions(int x) { + bool a = true && true; + int b = (true) ? x : x; +} + +typedef unsigned long size_t; + +namespace std { + enum class align_val_t : size_t {}; +} + +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 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); + +struct SizedDealloc { + char a[32]; + void* operator new(size_t); + void* operator new[](size_t); + void operator delete(void*, size_t); + void operator delete[](void*, size_t); +}; + +struct alignas(128) Overaligned { + char a[256]; +}; + +struct DefaultCtorWithDefaultParam { + DefaultCtorWithDefaultParam(double d = 1.0); +}; + +void OperatorNew() { + new int; // No constructor + new(1.0f) int; // Placement new, no constructor + new int(); // Zero-init + new String(); // Constructor + new(1.0f) String("hello"); // Placement new, constructor with args + new Overaligned; // Aligned new + new(1.0f) Overaligned(); // Placement aligned new with zero-init +} + +void OperatorNewArray(int n) { + new int[10]; // Constant size + new int[n]; // No constructor + new(1.0f) int[n]; // Placement new, no constructor + new String[n]; // Constructor + new Overaligned[n]; // Aligned new + new(1.0f) Overaligned[10]; // Aligned placement new + new DefaultCtorWithDefaultParam[n]; + new int[n] { 0, 1, 2 }; +} + +int designatedInit() { + int a1[1000] = { [2] = 10002, [900] = 10900 }; + return a1[900]; +} + +#if 0 +void OperatorDelete() { + delete static_cast(nullptr); // No destructor + delete static_cast(nullptr); // Non-virtual destructor, with size. + delete static_cast(nullptr); // No destructor, with size. + delete static_cast(nullptr); // No destructor, with size and alignment. + delete static_cast(nullptr); // Virtual destructor +} + +void OperatorDeleteArray() { + delete[] static_cast(nullptr); // No destructor + delete[] static_cast(nullptr); // Non-virtual destructor, with size. + delete[] static_cast(nullptr); // No destructor, with size. + delete[] static_cast(nullptr); // No destructor, with size and alignment. + delete[] static_cast(nullptr); // Virtual destructor +} +#endif + +// semmle-extractor-options: -std=c++17 diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 0c361cfb374..5f5dc4d3f5d 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -3885,3 +3885,49 @@ ir.cpp: # 950| v0_65(void) = ReturnVoid : # 950| v0_66(void) = UnmodeledUse : mu* # 950| v0_67(void) = ExitFunction : + +# 961| designatedInit() -> int +# 961| Block 0 +# 961| v0_0(void) = EnterFunction : +# 961| mu0_1(unknown) = UnmodeledDefinition : +# 962| r0_2(glval) = VariableAddress[a1] : +# 962| r0_3(int) = Constant[0] : +# 962| r0_4(glval) = PointerAdd : r0_2, r0_3 +# 962| r0_5(unknown[8]) = Constant[0] : +# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5 +#-----| Goto -> Block 2 + +# 962| Block 1 +# 962| r1_0(int) = Constant[900] : +# 962| r1_1(glval) = PointerAdd : r0_2, r1_0 +# 962| r1_2(int) = Constant[10900] : +# 962| mu1_3(int) = Store : r1_1, r1_2 +# 962| r1_4(int) = Constant[901] : +# 962| r1_5(glval) = PointerAdd : r0_2, r1_4 +# 962| r1_6(unknown[396]) = Constant[0] : +# 962| mu1_7(unknown[396]) = Store : r1_5, r1_6 +#-----| Goto -> Block 2 + +# 963| Block 2 +# 963| r2_0(glval) = VariableAddress[#return] : +# 963| r2_1(glval) = VariableAddress[a1] : +# 963| r2_2(int *) = Convert : r2_1 +# 963| r2_3(int) = Constant[900] : +# 963| r2_4(int *) = PointerAdd[4] : r2_2, r2_3 +# 963| r2_5(int) = Load : r2_4, mu0_1 +# 963| mu2_6(int) = Store : r2_0, r2_5 +# 961| r2_7(glval) = VariableAddress[#return] : +# 961| v2_8(void) = ReturnValue : r2_7, mu0_1 +# 961| v2_9(void) = UnmodeledUse : mu* +# 961| v2_10(void) = ExitFunction : + +# 962| Block 3 +# 962| r3_0(int) = Constant[2] : +# 962| r3_1(glval) = PointerAdd : r0_2, r3_0 +# 962| r3_2(int) = Constant[10002] : +# 962| mu3_3(int) = Store : r3_1, r3_2 +# 962| r3_4(int) = Constant[3] : +# 962| r3_5(glval) = PointerAdd : r0_2, r3_4 +# 962| r3_6(unknown[3588]) = Constant[0] : +# 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6 +#-----| Goto -> Block 2 diff --git a/cpp/ql/test/library-tests/ir/ir/ssa_block_count.expected b/cpp/ql/test/library-tests/ir/ir/ssa_block_count.expected index 4bd31c2a64f..0ef298fee3d 100644 --- a/cpp/ql/test/library-tests/ir/ir/ssa_block_count.expected +++ b/cpp/ql/test/library-tests/ir/ir/ssa_block_count.expected @@ -92,6 +92,7 @@ | IR: VarArgs | 1 | | IR: VirtualMemberFunction | 1 | | IR: WhileStatements | 4 | +| IR: designatedInit | 4 | | IR: min | 4 | | IR: operator= | 1 | | IR: ~Base | 1 | diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_ir.expected index c26bcce5810..af2385fb03d 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_ir.expected @@ -3906,3 +3906,49 @@ ir.cpp: # 950| v0_65(void) = ReturnVoid : # 950| v0_66(void) = UnmodeledUse : mu* # 950| v0_67(void) = ExitFunction : + +# 961| designatedInit() -> int +# 961| Block 0 +# 961| v0_0(void) = EnterFunction : +# 961| mu0_1(unknown) = UnmodeledDefinition : +# 962| r0_2(glval) = VariableAddress[a1] : +# 962| r0_3(int) = Constant[0] : +# 962| r0_4(glval) = PointerAdd : r0_2, r0_3 +# 962| r0_5(unknown[8]) = Constant[0] : +# 962| mu0_6(unknown[8]) = Store : r0_4, r0_5 +#-----| Goto -> Block 2 + +# 962| Block 1 +# 962| r1_0(int) = Constant[900] : +# 962| r1_1(glval) = PointerAdd : r0_2, r1_0 +# 962| r1_2(int) = Constant[10900] : +# 962| mu1_3(int) = Store : r1_1, r1_2 +# 962| r1_4(int) = Constant[901] : +# 962| r1_5(glval) = PointerAdd : r0_2, r1_4 +# 962| r1_6(unknown[396]) = Constant[0] : +# 962| mu1_7(unknown[396]) = Store : r1_5, r1_6 +#-----| Goto -> Block 2 + +# 963| Block 2 +# 963| r2_0(glval) = VariableAddress[#return] : +# 963| r2_1(glval) = VariableAddress[a1] : +# 963| r2_2(int *) = Convert : r2_1 +# 963| r2_3(int) = Constant[900] : +# 963| r2_4(int *) = PointerAdd[4] : r2_2, r2_3 +# 963| r2_5(int) = Load : r2_4, mu0_1 +# 963| m2_6(int) = Store : r2_0, r2_5 +# 961| r2_7(glval) = VariableAddress[#return] : +# 961| v2_8(void) = ReturnValue : r2_7, m2_6 +# 961| v2_9(void) = UnmodeledUse : mu* +# 961| v2_10(void) = ExitFunction : + +# 962| Block 3 +# 962| r3_0(int) = Constant[2] : +# 962| r3_1(glval) = PointerAdd : r0_2, r3_0 +# 962| r3_2(int) = Constant[10002] : +# 962| mu3_3(int) = Store : r3_1, r3_2 +# 962| r3_4(int) = Constant[3] : +# 962| r3_5(glval) = PointerAdd : r0_2, r3_4 +# 962| r3_6(unknown[3588]) = Constant[0] : +# 962| mu3_7(unknown[3588]) = Store : r3_5, r3_6 +#-----| Goto -> Block 2 diff --git a/cpp/ql/test/library-tests/literals/aggregate_literals/aggregate_literals.c b/cpp/ql/test/library-tests/literals/aggregate_literals/aggregate_literals.c index 22992df95ea..ee5c611b43f 100644 --- a/cpp/ql/test/library-tests/literals/aggregate_literals/aggregate_literals.c +++ b/cpp/ql/test/library-tests/literals/aggregate_literals/aggregate_literals.c @@ -1,102 +1,102 @@ -struct someStruct { - int i; - int j; -}; - -struct someOtherStruct { - int a; - int b; -}; - -union someUnion { - int n; - double d; -}; - -void f(int x, int y) { - struct someStruct sInit1 = { - .i = x + x, - .j = y - y, - }; - - struct someStruct sInit2 = { x + x, y - y }; - - struct someStruct ss[] = {{x + x, y - y}, {x * x, y / y}}; - - struct someStruct sInit3 = { x }; - - struct someStruct sInit4 = { .j = y }; - - int aInit1[2] = { x, y }; - - int aInit2[2] = { x }; - - int aInit3[2] = { [1] = y }; - - union someUnion uInit1 = { x }; - union someUnion uInit2 = { .n = x }; - union someUnion uInit3 = { .d = 5.0 }; -} - -struct complexStruct { - struct someStruct sss[3]; - int as[3]; - struct someOtherStruct soss[3]; - int z; -}; - -void g(int x, int y) { - // Nested aggregate designated initializers - struct complexStruct complexInit1 = { - .as = { - [2] = x, - [0] = y, - x+y // as[1] - }, - .z = 42, - .soss = { - [1] = { - .a = x+y, - .b = x-y - }, - [0] = { - .b = x*y, - .a = x/y - } - // soss[2] is value initializaed - } - // sss is value initialized - }; - - // Nested aggregate non-designated initializers - struct complexStruct complexInit2 = { - { // sss - { // sss[0] - x, // sss[0].i - y // sss[0].j - }, - { // sss[1] - x+1, // sss[1].i - // sss[1].j is value initialized - } - // ss[2] is value initialized - }, - { // as - 99, // as[0] - x*y // as[1] - // as[2] is value initialized - }, - { // soss - { // soss[0] - 123, // soss[0].a - y+1 // soss[0].b - }, - { // soss[1] - x, // soss[1].a - // soss[1].b is value initialized - } - // soss[2] is value initialized - } - // z is value initialized - }; -} +struct someStruct { + int i; + int j; +}; + +struct someOtherStruct { + int a; + int b; +}; + +union someUnion { + int n; + double d; +}; + +void f(int x, int y) { + struct someStruct sInit1 = { + .i = x + x, + .j = y - y, + }; + + struct someStruct sInit2 = { x + x, y - y }; + + struct someStruct ss[] = {{x + x, y - y}, {x * x, y / y}}; + + struct someStruct sInit3 = { x }; + + struct someStruct sInit4 = { .j = y }; + + int aInit1[2] = { x, y }; + + int aInit2[2] = { x }; + + int aInit3[2] = { [1] = y }; + + union someUnion uInit1 = { x }; + union someUnion uInit2 = { .n = x }; + union someUnion uInit3 = { .d = 5.0 }; +} + +struct complexStruct { + struct someStruct sss[3]; + int as[3]; + struct someOtherStruct soss[3]; + int z; +}; + +void g(int x, int y) { + // Nested aggregate designated initializers + struct complexStruct complexInit1 = { + .as = { + [2] = x, + [0] = y, + x+y // as[1] + }, + .z = 42, + .soss = { + [1] = { + .a = x+y, + .b = x-y + }, + [0] = { + .b = x*y, + .a = x/y + } + // soss[2] is value initializaed + } + // sss is value initialized + }; + + // Nested aggregate non-designated initializers + struct complexStruct complexInit2 = { + { // sss + { // sss[0] + x, // sss[0].i + y // sss[0].j + }, + { // sss[1] + x+1, // sss[1].i + // sss[1].j is value initialized + } + // ss[2] is value initialized + }, + { // as + 99, // as[0] + x*y // as[1] + // as[2] is value initialized + }, + { // soss + { // soss[0] + 123, // soss[0].a + y+1 // soss[0].b + }, + { // soss[1] + x, // soss[1].a + // soss[1].b is value initialized + } + // soss[2] is value initialized + } + // z is value initialized + }; +} diff --git a/cpp/ql/test/library-tests/literals/aggregate_literals/aggregate_literals_cpp.cpp b/cpp/ql/test/library-tests/literals/aggregate_literals/aggregate_literals_cpp.cpp index ba1acfbe0ff..8b335fe3cae 100644 --- a/cpp/ql/test/library-tests/literals/aggregate_literals/aggregate_literals_cpp.cpp +++ b/cpp/ql/test/library-tests/literals/aggregate_literals/aggregate_literals_cpp.cpp @@ -1,28 +1,28 @@ -struct StructWithBitfields { - void Method(); - - unsigned int a : 12; - - static int s; // Static member variables aren't initialized - - unsigned int b : 5; - unsigned int : 15; // Unnamed bitfields aren't initialized - unsigned int c : 7; -}; - -union UnionWithMethods { - void Method(); - - static int s; - - double d; - int x; -}; - -void Init(int x, int y, int z) { - StructWithBitfields s1 = { x, y, z }; - StructWithBitfields s2 = { x, y }; // s2.c is value initialized - StructWithBitfields s3 = {}; // s3 is value initialized - UnionWithMethods u1 = { x }; - UnionWithMethods u2 = {}; -} +struct StructWithBitfields { + void Method(); + + unsigned int a : 12; + + static int s; // Static member variables aren't initialized + + unsigned int b : 5; + unsigned int : 15; // Unnamed bitfields aren't initialized + unsigned int c : 7; +}; + +union UnionWithMethods { + void Method(); + + static int s; + + double d; + int x; +}; + +void Init(int x, int y, int z) { + StructWithBitfields s1 = { x, y, z }; + StructWithBitfields s2 = { x, y }; // s2.c is value initialized + StructWithBitfields s3 = {}; // s3 is value initialized + UnionWithMethods u1 = { x }; + UnionWithMethods u2 = {}; +} diff --git a/cpp/ql/test/library-tests/loops/loops.cpp b/cpp/ql/test/library-tests/loops/loops.cpp index e87c918225c..44450e745b0 100644 --- a/cpp/ql/test/library-tests/loops/loops.cpp +++ b/cpp/ql/test/library-tests/loops/loops.cpp @@ -1,36 +1,36 @@ -void update(bool b); -void init(int &i); -bool cond(int i); -void update(int &i); - -void test_while() -{ - bool b; - - b = true; - while (b) update(b); - - do - { - update(b); - } while (b); -} - -void test_for() -{ - int i, j; - - for (i = 0; i < 10; i++) { - } - - for (j = 10; j >= 0; ) j--; - - for (i = 0, j = 0; i < 10; i++, j++) { - } - - for (init(i); cond(i); update(i)) { - } - - for ((i = 100); (i >= 0); (i--)) { - } -} +void update(bool b); +void init(int &i); +bool cond(int i); +void update(int &i); + +void test_while() +{ + bool b; + + b = true; + while (b) update(b); + + do + { + update(b); + } while (b); +} + +void test_for() +{ + int i, j; + + for (i = 0; i < 10; i++) { + } + + for (j = 10; j >= 0; ) j--; + + for (i = 0, j = 0; i < 10; i++, j++) { + } + + for (init(i); cond(i); update(i)) { + } + + for ((i = 100); (i >= 0); (i--)) { + } +} diff --git a/cpp/ql/test/library-tests/namespaces/namespaces/namespaces.cpp b/cpp/ql/test/library-tests/namespaces/namespaces/namespaces.cpp index f75c9883dbb..e9a28fe1b1f 100644 --- a/cpp/ql/test/library-tests/namespaces/namespaces/namespaces.cpp +++ b/cpp/ql/test/library-tests/namespaces/namespaces/namespaces.cpp @@ -1,44 +1,44 @@ -namespace A { - -} - -namespace B { - -} - -namespace C { - - namespace D { - - inline int f() { return 0; } - - class E { - - void g(int p) { - int a; - { - int b; - } - } - - }; - - } - -} - -namespace B { - - int x = C::D::f(); - -} - -namespace std { - -} - -int globalInt; - -void globalIntUser(void) { - extern int globalInt; -} +namespace A { + +} + +namespace B { + +} + +namespace C { + + namespace D { + + inline int f() { return 0; } + + class E { + + void g(int p) { + int a; + { + int b; + } + } + + }; + + } + +} + +namespace B { + + int x = C::D::f(); + +} + +namespace std { + +} + +int globalInt; + +void globalIntUser(void) { + extern int globalInt; +} diff --git a/cpp/ql/test/library-tests/namespaces/same_name/same_name.cpp b/cpp/ql/test/library-tests/namespaces/same_name/same_name.cpp index 6e7d7204e73..8f45748a1d7 100644 --- a/cpp/ql/test/library-tests/namespaces/same_name/same_name.cpp +++ b/cpp/ql/test/library-tests/namespaces/same_name/same_name.cpp @@ -1,16 +1,16 @@ - -const int c = 1; - -namespace namespace_a -{ - const int c = 1; -} - -namespace namespace_b -{ - //const int c = 1; - // - // this example is causing a DBCheck failure along the lines of: - // - // [INVALID_KEY] Relation namespacembrs((@namespace parentid, unique @namespacembr memberid)): Value 132 of key field memberid occurs in several tuples. Two such tuples are: (134,132) and (144,132) -} + +const int c = 1; + +namespace namespace_a +{ + const int c = 1; +} + +namespace namespace_b +{ + //const int c = 1; + // + // this example is causing a DBCheck failure along the lines of: + // + // [INVALID_KEY] Relation namespacembrs((@namespace parentid, unique @namespacembr memberid)): Value 132 of key field memberid occurs in several tuples. Two such tuples are: (134,132) and (144,132) +} diff --git a/cpp/ql/test/library-tests/operators/operators.cpp b/cpp/ql/test/library-tests/operators/operators.cpp index 79034297725..164d2c19e84 100644 --- a/cpp/ql/test/library-tests/operators/operators.cpp +++ b/cpp/ql/test/library-tests/operators/operators.cpp @@ -1,27 +1,27 @@ -class Name { - const char* s; -}; - -class Table { - Name* p; - int sz; -public: - // See JIRA 521. Including a non-default copy constructor for now. - Table(const Table& other) { } - Table(int s=15) { p = new Name[sz=s]; } // constructor - ~Table() { delete[] p; } - Name* lookup (const char*); - bool insert(Name*); -}; - -void foo() { - Table t1; // call to user-defined constructor - Table t2(t1); // call to default copy constructor - t2.insert(0); -} - -// This used to have TRAP import errors -struct A { A() {} A(A&) {} } a; -A operator+(int, A) { return a; } -int f_A() { 0 + a; } - +class Name { + const char* s; +}; + +class Table { + Name* p; + int sz; +public: + // See JIRA 521. Including a non-default copy constructor for now. + Table(const Table& other) { } + Table(int s=15) { p = new Name[sz=s]; } // constructor + ~Table() { delete[] p; } + Name* lookup (const char*); + bool insert(Name*); +}; + +void foo() { + Table t1; // call to user-defined constructor + Table t2(t1); // call to default copy constructor + t2.insert(0); +} + +// This used to have TRAP import errors +struct A { A() {} A(A&) {} } a; +A operator+(int, A) { return a; } +int f_A() { 0 + a; } + diff --git a/cpp/ql/test/library-tests/padding/size_asserts.h b/cpp/ql/test/library-tests/padding/size_asserts.h index 674257cba41..1b68ed8472d 100644 --- a/cpp/ql/test/library-tests/padding/size_asserts.h +++ b/cpp/ql/test/library-tests/padding/size_asserts.h @@ -1,46 +1,46 @@ -// Static assert macro -#define CASSERT(condition) typedef char cassertTypedef[((condition) != 0) ? 1 : -1] - -#if defined(_MSC_VER) -#define CASSERT_MSVC(condition) CASSERT(condition) -#define CASSERT_GCC(condition) -#if defined(_WIN64) -#define TARGET_BIT_SIZE 64 -#else -#define TARGET_BIT_SIZE 32 -#endif -#elif defined(__GNUC__) -#define CASSERT_MSVC(condition) -#define CASSERT_GCC(condition) CASSERT(condition) -#if defined(__x86_64) -#define TARGET_BIT_SIZE 64 -#else -#define TARGET_BIT_SIZE 32 -#endif -#else -CASSERT(0); -#endif - -#if defined(_MSC_VER) && (TARGET_BIT_SIZE == 32) -#define CASSERT_MSVC32(condition) CASSERT(condition) -#else -#define CASSERT_MSVC32(condition) -#endif - -#if defined(_MSC_VER) && (TARGET_BIT_SIZE == 64) -#define CASSERT_MSVC64(condition) CASSERT(condition) -#else -#define CASSERT_MSVC64(condition) -#endif - -#if defined(__GNUC__) && (TARGET_BIT_SIZE == 32) -#define CASSERT_GCC32(condition) CASSERT(condition) -#else -#define CASSERT_GCC32(condition) -#endif - -#if defined(__GNUC__) && (TARGET_BIT_SIZE == 64) -#define CASSERT_GCC64(condition) CASSERT(condition) -#else -#define CASSERT_GCC64(condition) -#endif +// Static assert macro +#define CASSERT(condition) typedef char cassertTypedef[((condition) != 0) ? 1 : -1] + +#if defined(_MSC_VER) +#define CASSERT_MSVC(condition) CASSERT(condition) +#define CASSERT_GCC(condition) +#if defined(_WIN64) +#define TARGET_BIT_SIZE 64 +#else +#define TARGET_BIT_SIZE 32 +#endif +#elif defined(__GNUC__) +#define CASSERT_MSVC(condition) +#define CASSERT_GCC(condition) CASSERT(condition) +#if defined(__x86_64) +#define TARGET_BIT_SIZE 64 +#else +#define TARGET_BIT_SIZE 32 +#endif +#else +CASSERT(0); +#endif + +#if defined(_MSC_VER) && (TARGET_BIT_SIZE == 32) +#define CASSERT_MSVC32(condition) CASSERT(condition) +#else +#define CASSERT_MSVC32(condition) +#endif + +#if defined(_MSC_VER) && (TARGET_BIT_SIZE == 64) +#define CASSERT_MSVC64(condition) CASSERT(condition) +#else +#define CASSERT_MSVC64(condition) +#endif + +#if defined(__GNUC__) && (TARGET_BIT_SIZE == 32) +#define CASSERT_GCC32(condition) CASSERT(condition) +#else +#define CASSERT_GCC32(condition) +#endif + +#if defined(__GNUC__) && (TARGET_BIT_SIZE == 64) +#define CASSERT_GCC64(condition) CASSERT(condition) +#else +#define CASSERT_GCC64(condition) +#endif diff --git a/cpp/ql/test/library-tests/parameters/parameters/parameters.cpp b/cpp/ql/test/library-tests/parameters/parameters/parameters.cpp index 1c85d65409b..c0965c33172 100644 --- a/cpp/ql/test/library-tests/parameters/parameters/parameters.cpp +++ b/cpp/ql/test/library-tests/parameters/parameters/parameters.cpp @@ -1,28 +1,28 @@ -typedef int (*CallbackFn)(int a, int b); - -int Callback_1(int a, int b) -{ - return a + b; -} - -int Callback_2(int a, int b) -{ - return a; -} - -int Callback_3(int, int b) -{ - return b; -} - -void Dispatch(int n, int a, int b, int c, int) -{ - CallbackFn pFn; - switch(n) - { - case 0: pFn = &Callback_1; break; - case 1: pFn = &Callback_2; break; - default: pFn = &Callback_3; break; - } - (*pFn)(a,b); -} +typedef int (*CallbackFn)(int a, int b); + +int Callback_1(int a, int b) +{ + return a + b; +} + +int Callback_2(int a, int b) +{ + return a; +} + +int Callback_3(int, int b) +{ + return b; +} + +void Dispatch(int n, int a, int b, int c, int) +{ + CallbackFn pFn; + switch(n) + { + case 0: pFn = &Callback_1; break; + case 1: pFn = &Callback_2; break; + default: pFn = &Callback_3; break; + } + (*pFn)(a,b); +} diff --git a/cpp/ql/test/library-tests/preprocessor/include/guarded.h b/cpp/ql/test/library-tests/preprocessor/include/guarded.h index 96fb298d5c9..fb7c9149e9f 100644 --- a/cpp/ql/test/library-tests/preprocessor/include/guarded.h +++ b/cpp/ql/test/library-tests/preprocessor/include/guarded.h @@ -1,8 +1,8 @@ -// guarded.h - -#ifndef GUARDED_H -#define GUARDED_H - - // ... content ... - +// guarded.h + +#ifndef GUARDED_H +#define GUARDED_H + + // ... content ... + #endif // GUARDED_H \ No newline at end of file diff --git a/cpp/ql/test/library-tests/preprocessor/include/unguarded.h b/cpp/ql/test/library-tests/preprocessor/include/unguarded.h index 14f174c8729..bf1b9844e68 100644 --- a/cpp/ql/test/library-tests/preprocessor/include/unguarded.h +++ b/cpp/ql/test/library-tests/preprocessor/include/unguarded.h @@ -1,3 +1,3 @@ -// unguarded.h - -// ... content ... +// unguarded.h + +// ... content ... diff --git a/cpp/ql/test/library-tests/preprocessor/linedirective/header.h b/cpp/ql/test/library-tests/preprocessor/linedirective/header.h index 51fb5f568d6..6865877d950 100644 --- a/cpp/ql/test/library-tests/preprocessor/linedirective/header.h +++ b/cpp/ql/test/library-tests/preprocessor/linedirective/header.h @@ -1,3 +1,3 @@ -// header.h - -// ... content ... +// header.h + +// ... content ... diff --git a/cpp/ql/test/library-tests/preprocessor/linedirective/line.h b/cpp/ql/test/library-tests/preprocessor/linedirective/line.h index 5ec8cc56e1f..1b4fc1a6aee 100644 --- a/cpp/ql/test/library-tests/preprocessor/linedirective/line.h +++ b/cpp/ql/test/library-tests/preprocessor/linedirective/line.h @@ -1,14 +1,14 @@ -// line.h - -#line 100 "line.h" - -#include "header.h" - -void myLineFunction(); - -#define MYLINEDEFINE (1) - -struct myLineStruct -{ - int v; -}; +// line.h + +#line 100 "line.h" + +#include "header.h" + +void myLineFunction(); + +#define MYLINEDEFINE (1) + +struct myLineStruct +{ + int v; +}; diff --git a/cpp/ql/test/library-tests/preprocessor/linedirective/system.h b/cpp/ql/test/library-tests/preprocessor/linedirective/system.h index eec178192a5..407507af89a 100644 --- a/cpp/ql/test/library-tests/preprocessor/linedirective/system.h +++ b/cpp/ql/test/library-tests/preprocessor/linedirective/system.h @@ -1,14 +1,14 @@ -// system.h - -#pragma GCC system_header - -#include "header.h" - -void mySystemFunction(); - -#define MYSYSTEMDEFINE (2) - -struct mySystemStruct -{ - int v; -}; +// system.h + +#pragma GCC system_header + +#include "header.h" + +void mySystemFunction(); + +#define MYSYSTEMDEFINE (2) + +struct mySystemStruct +{ + int v; +}; diff --git a/cpp/ql/test/library-tests/scopes/scopes/scopes.cpp b/cpp/ql/test/library-tests/scopes/scopes/scopes.cpp index 3e1353e1ff7..70dc0a195dd 100644 --- a/cpp/ql/test/library-tests/scopes/scopes/scopes.cpp +++ b/cpp/ql/test/library-tests/scopes/scopes/scopes.cpp @@ -1,104 +1,104 @@ - -class A { - -}; - - -class B { - -}; - -class C: A, B { - -}; - -class D: C { - - class E; - -}; - -class D::E { - - class F; - - class G { - - }; - -}; - -class D::E::F: D::E::G { - void doubleNestedFunction() {} -}; - -void f(int a, int b) { - bool c = a==b; - - switch (a) - { - default: - } -} - -void g(); - -struct S { - void af() { - - } - void ag(); -}; - -void g() { - S s; - s.ag(); -} - -class Name { - const char* s; -}; - -class Table { - Name* p; - int sz; -public: - Table(int s=15) { p = new Name[sz=s]; } // constructor - ~Table() { delete[] p; } - Name* lookup (const char*); - bool insert(Name*); -}; - -extern "C" int strlen(const char*); - -namespace One -{ - template - class H - { - T t; - }; - - H h_short; - H h_long; - - namespace Two - { - enum myEnum - { - myOne, - myTwo, - myThree - }; - }; - - class I - { - enum myEnum2 - { - Alpha, - Beta, - Gamma - }; - }; + +class A { + +}; + + +class B { + +}; + +class C: A, B { + +}; + +class D: C { + + class E; + +}; + +class D::E { + + class F; + + class G { + + }; + +}; + +class D::E::F: D::E::G { + void doubleNestedFunction() {} +}; + +void f(int a, int b) { + bool c = a==b; + + switch (a) + { + default: + } +} + +void g(); + +struct S { + void af() { + + } + void ag(); +}; + +void g() { + S s; + s.ag(); +} + +class Name { + const char* s; +}; + +class Table { + Name* p; + int sz; +public: + Table(int s=15) { p = new Name[sz=s]; } // constructor + ~Table() { delete[] p; } + Name* lookup (const char*); + bool insert(Name*); +}; + +extern "C" int strlen(const char*); + +namespace One +{ + template + class H + { + T t; + }; + + H h_short; + H h_long; + + namespace Two + { + enum myEnum + { + myOne, + myTwo, + myThree + }; + }; + + class I + { + enum myEnum2 + { + Alpha, + Beta, + Gamma + }; + }; }; \ No newline at end of file diff --git a/cpp/ql/test/library-tests/sideEffects/exprs/exprs.cpp b/cpp/ql/test/library-tests/sideEffects/exprs/exprs.cpp index d28e8513e84..30b0f5cf6fc 100644 --- a/cpp/ql/test/library-tests/sideEffects/exprs/exprs.cpp +++ b/cpp/ql/test/library-tests/sideEffects/exprs/exprs.cpp @@ -1,40 +1,40 @@ - -class MyIterator - { -public: - MyIterator &operator++() - { - return (*this); - } - - MyIterator &operator--() - { - v--; - return (*this); - } - -private: - int v; - }; - -void f2() { - MyIterator mi; - - ++mi; - --mi; -} - -template void myTemplateFunction() { - static MyIterator mi; - static int i; - static T t; - - ++mi; // pure - ++i; // impure - ++t; // varies -} - -void f3() { - myTemplateFunction(); - myTemplateFunction(); -} + +class MyIterator + { +public: + MyIterator &operator++() + { + return (*this); + } + + MyIterator &operator--() + { + v--; + return (*this); + } + +private: + int v; + }; + +void f2() { + MyIterator mi; + + ++mi; + --mi; +} + +template void myTemplateFunction() { + static MyIterator mi; + static int i; + static T t; + + ++mi; // pure + ++i; // impure + ++t; // varies +} + +void f3() { + myTemplateFunction(); + myTemplateFunction(); +} diff --git a/cpp/ql/test/library-tests/specifiers/specifiers.cpp b/cpp/ql/test/library-tests/specifiers/specifiers.cpp index db40595b09c..c103e4198c7 100644 --- a/cpp/ql/test/library-tests/specifiers/specifiers.cpp +++ b/cpp/ql/test/library-tests/specifiers/specifiers.cpp @@ -1,22 +1,22 @@ -extern int i; -extern int i; -extern int i; - -const int c = 7; -const double pi = 3.1415926535897932385; - -unsigned a; - -unsigned int b; -int b2; - - int * const int_pointer1 = &b2; -const int * int_pointer2 = &c; // Note: int_pointer2 is not const itself -const int * const int_pointer3 = &c; - -typedef char* Pchar; - -const char* kings[] = { "Antigonus", "Seleucus", "Ptolemy" }; - -int* p, q; -int v[10], *pv; +extern int i; +extern int i; +extern int i; + +const int c = 7; +const double pi = 3.1415926535897932385; + +unsigned a; + +unsigned int b; +int b2; + + int * const int_pointer1 = &b2; +const int * int_pointer2 = &c; // Note: int_pointer2 is not const itself +const int * const int_pointer3 = &c; + +typedef char* Pchar; + +const char* kings[] = { "Antigonus", "Seleucus", "Ptolemy" }; + +int* p, q; +int v[10], *pv; diff --git a/cpp/ql/test/library-tests/string_analysis/string_analysis.cpp b/cpp/ql/test/library-tests/string_analysis/string_analysis.cpp index 283baabd2ac..7d98961f04b 100644 --- a/cpp/ql/test/library-tests/string_analysis/string_analysis.cpp +++ b/cpp/ql/test/library-tests/string_analysis/string_analysis.cpp @@ -1,44 +1,44 @@ -int main(int argc, char *argv[]) -{ - char *str1, *str2, *str3, *result; - int cond1, cond2, cond3, cond4; - - str1 = "1"; - str2 = "22"; - str3 = "333"; - - result = str1; // max length 1 - if (cond1) - { - result = (cond2 ? str2 : str3); // max length 3 - } - result = (cond3 ? str1 : result); // max length 3 - result = (cond4 ? str1 : argv[0]); // max unknown - - return 0; -} - -namespace std -{ - class string - { - public: - string(char *_str) : str(_str) {}; - ~string() {}; - - string &operator=(string &other) { - str = other.str; - }; - - private: - char *str; - }; -} - -void more_cases() -{ - wchar_t *wstr1 = L"4444"; - wchar_t *wstr2 = wstr1; - std::string str1 = "666666"; - std::string str2 = str1; -} +int main(int argc, char *argv[]) +{ + char *str1, *str2, *str3, *result; + int cond1, cond2, cond3, cond4; + + str1 = "1"; + str2 = "22"; + str3 = "333"; + + result = str1; // max length 1 + if (cond1) + { + result = (cond2 ? str2 : str3); // max length 3 + } + result = (cond3 ? str1 : result); // max length 3 + result = (cond4 ? str1 : argv[0]); // max unknown + + return 0; +} + +namespace std +{ + class string + { + public: + string(char *_str) : str(_str) {}; + ~string() {}; + + string &operator=(string &other) { + str = other.str; + }; + + private: + char *str; + }; +} + +void more_cases() +{ + wchar_t *wstr1 = L"4444"; + wchar_t *wstr2 = wstr1; + std::string str1 = "666666"; + std::string str2 = str1; +} diff --git a/cpp/ql/test/library-tests/structs/compatible_cpp/b1.cpp b/cpp/ql/test/library-tests/structs/compatible_cpp/b1.cpp index c7d839b4874..760147d60ff 100644 --- a/cpp/ql/test/library-tests/structs/compatible_cpp/b1.cpp +++ b/cpp/ql/test/library-tests/structs/compatible_cpp/b1.cpp @@ -24,3 +24,9 @@ class Damson { int damson_x; void foo(); }; + +namespace unrelated { + class AppleCompatible { + long apple_x; + }; +} diff --git a/cpp/ql/test/library-tests/structs/compatible_cpp/compatible.expected b/cpp/ql/test/library-tests/structs/compatible_cpp/compatible.expected index 4b631dde98b..326fea4210f 100644 --- a/cpp/ql/test/library-tests/structs/compatible_cpp/compatible.expected +++ b/cpp/ql/test/library-tests/structs/compatible_cpp/compatible.expected @@ -32,6 +32,9 @@ | b1.cpp:23:7:23:12 | Damson | 5 members | 2 locations | 1 | foo | | b1.cpp:23:7:23:12 | Damson | 5 members | 2 locations | 2 | operator= | | b1.cpp:23:7:23:12 | Damson | 5 members | 2 locations | 3 | operator= | +| b1.cpp:29:9:29:23 | AppleCompatible | 3 members | 1 locations | 0 | apple_x | +| b1.cpp:29:9:29:23 | AppleCompatible | 3 members | 1 locations | 1 | operator= | +| b1.cpp:29:9:29:23 | AppleCompatible | 3 members | 1 locations | 2 | operator= | | b2.cpp:2:7:2:21 | AppleCompatible | 3 members | 2 locations | 0 | apple_x | | b2.cpp:2:7:2:21 | AppleCompatible | 3 members | 2 locations | 1 | operator= | | b2.cpp:2:7:2:21 | AppleCompatible | 3 members | 2 locations | 2 | operator= | diff --git a/cpp/ql/test/library-tests/structs/compatible_cpp/compatible_types.expected b/cpp/ql/test/library-tests/structs/compatible_cpp/compatible_types.expected index df2a178f667..f9446f1b19a 100644 --- a/cpp/ql/test/library-tests/structs/compatible_cpp/compatible_types.expected +++ b/cpp/ql/test/library-tests/structs/compatible_cpp/compatible_types.expected @@ -10,6 +10,7 @@ | b1.cpp:11:7:11:22 | BananaCompatible | 0 | file://:0:0:0:0 | int | 1 types | | b1.cpp:16:7:16:12 | Cherry | 0 | file://:0:0:0:0 | int | 1 types | | b1.cpp:23:7:23:12 | Damson | 0 | file://:0:0:0:0 | int | 1 types | +| b1.cpp:29:9:29:23 | AppleCompatible | 0 | file://:0:0:0:0 | long | 1 types | | b2.cpp:2:7:2:21 | AppleCompatible | 0 | file://:0:0:0:0 | int | 1 types | | b2.cpp:9:7:9:22 | BananaCompatible | 0 | file://:0:0:0:0 | int | 1 types | | b2.cpp:14:7:14:12 | Cherry | 0 | file://:0:0:0:0 | short | 1 types | diff --git a/cpp/ql/test/library-tests/structs/compatible_variables/a.c b/cpp/ql/test/library-tests/structs/compatible_variables/a.c index bac709efb95..6f6b1800d8b 100644 --- a/cpp/ql/test/library-tests/structs/compatible_variables/a.c +++ b/cpp/ql/test/library-tests/structs/compatible_variables/a.c @@ -1,14 +1,14 @@ -#include "h.h" - -// Provide a complete definition of Foo. -struct Foo { - int foo_x; -}; - -// This definition is incompatible with the one in b.c, so... -struct Bar { - int bar_y; -}; - -// ...we'd expect this declaration to create a separate variable in the db -extern struct Bar bar; +#include "h.h" + +// Provide a complete definition of Foo. +struct Foo { + int foo_x; +}; + +// This definition is incompatible with the one in b.c, so... +struct Bar { + int bar_y; +}; + +// ...we'd expect this declaration to create a separate variable in the db +extern struct Bar bar; diff --git a/cpp/ql/test/library-tests/structs/compatible_variables/b.c b/cpp/ql/test/library-tests/structs/compatible_variables/b.c index 5037af9500d..a7dd16e2d38 100644 --- a/cpp/ql/test/library-tests/structs/compatible_variables/b.c +++ b/cpp/ql/test/library-tests/structs/compatible_variables/b.c @@ -1,17 +1,17 @@ -// The extractor will not see a complete definition of Foo for this file. - -#include "h.h" - -// We want to check that these two variables don't get duplicated in the -// database. -void (*some_func_ptr)(struct Foo *foo); -struct Foo* foo_ptr1; -FooPtr foo_ptr2; - -// This definition is incompatible with the one in a.c, so... -struct Bar { - unsigned long bar_x; -}; - -// ...we'd expect this declaration to create a separate variable in the db -extern struct Bar bar; +// The extractor will not see a complete definition of Foo for this file. + +#include "h.h" + +// We want to check that these two variables don't get duplicated in the +// database. +void (*some_func_ptr)(struct Foo *foo); +struct Foo* foo_ptr1; +FooPtr foo_ptr2; + +// This definition is incompatible with the one in a.c, so... +struct Bar { + unsigned long bar_x; +}; + +// ...we'd expect this declaration to create a separate variable in the db +extern struct Bar bar; diff --git a/cpp/ql/test/library-tests/structs/compatible_variables/h.h b/cpp/ql/test/library-tests/structs/compatible_variables/h.h index 95cf6d42860..b94a97f9a4b 100644 --- a/cpp/ql/test/library-tests/structs/compatible_variables/h.h +++ b/cpp/ql/test/library-tests/structs/compatible_variables/h.h @@ -1,10 +1,10 @@ -// Provide an incomplete definition of Foo. -struct Foo; -typedef struct Foo* FooPtr; - -// When this file is included from a.c, the extractor will see a complete -// definition of Foo, but not when it's included b.c. We want to check that we -// don't see these variables duplicated in the database because of it. -extern void (*some_func_ptr)(struct Foo *foo); -extern struct Foo* foo_ptr1; -extern FooPtr foo_ptr2; +// Provide an incomplete definition of Foo. +struct Foo; +typedef struct Foo* FooPtr; + +// When this file is included from a.c, the extractor will see a complete +// definition of Foo, but not when it's included b.c. We want to check that we +// don't see these variables duplicated in the database because of it. +extern void (*some_func_ptr)(struct Foo *foo); +extern struct Foo* foo_ptr1; +extern FooPtr foo_ptr2; diff --git a/cpp/ql/test/library-tests/structs/incomplete_definition/a.h b/cpp/ql/test/library-tests/structs/incomplete_definition/a.h index d09cac85aa5..a051126f271 100644 --- a/cpp/ql/test/library-tests/structs/incomplete_definition/a.h +++ b/cpp/ql/test/library-tests/structs/incomplete_definition/a.h @@ -1,6 +1,6 @@ -// Incomplete definition of Foo -struct Foo; - -struct Bar { - Foo *cheese; -}; +// Incomplete definition of Foo +struct Foo; + +struct Bar { + Foo *cheese; +}; diff --git a/cpp/ql/test/library-tests/structs/incomplete_definition/pointerbasetype.expected b/cpp/ql/test/library-tests/structs/incomplete_definition/pointerbasetype.expected index 98a672ad435..801306a572a 100644 --- a/cpp/ql/test/library-tests/structs/incomplete_definition/pointerbasetype.expected +++ b/cpp/ql/test/library-tests/structs/incomplete_definition/pointerbasetype.expected @@ -1,2 +1,6 @@ | a.h:5:8:5:13 | cheese | y.cpp:4:8:4:10 | Foo | 3 | | x.cpp:3:6:3:10 | bar_x | a.h:4:8:4:10 | Bar | 3 | +| x.cpp:19:6:19:10 | foo_x | y.cpp:4:8:4:10 | Foo | 3 | +| x.cpp:23:5:23:17 | templateField | x.cpp:6:10:6:12 | Foo | 3 | +| x.cpp:23:5:23:17 | templateField | x.cpp:12:9:12:11 | Foo | 3 | +| x.cpp:26:18:26:29 | template_foo | x.cpp:22:7:22:14 | Template | 0 | diff --git a/cpp/ql/test/library-tests/structs/incomplete_definition/x.cpp b/cpp/ql/test/library-tests/structs/incomplete_definition/x.cpp index 5b2a352e3dd..e0e0338c831 100644 --- a/cpp/ql/test/library-tests/structs/incomplete_definition/x.cpp +++ b/cpp/ql/test/library-tests/structs/incomplete_definition/x.cpp @@ -1,3 +1,31 @@ -#include "a.h" - -Bar *bar_x; +#include "a.h" + +Bar *bar_x; + +namespace unrelated { + struct Foo { + short val; + }; +} + +struct ContainsAnotherFoo { + class Foo { + long val; + }; +}; + +// The type of `foo_x` should not refer to any of the above classes, none of +// which are named `Foo` in the global scope. +Foo *foo_x; + +template +class Template { + T templateField; +}; + +Template *template_foo; + +// Instantiation of the template with unrelated classes named `Foo` should not +// get mixed up with the instantiation above. +template class Template; +template class Template; diff --git a/cpp/ql/test/library-tests/structs/incomplete_definition/y.cpp b/cpp/ql/test/library-tests/structs/incomplete_definition/y.cpp index 6059af31766..ae8de1d55fa 100644 --- a/cpp/ql/test/library-tests/structs/incomplete_definition/y.cpp +++ b/cpp/ql/test/library-tests/structs/incomplete_definition/y.cpp @@ -1,8 +1,8 @@ -#include "a.h" - -// Completes definition of Foo -struct Foo { - int val; -}; - -Bar bar_y; +#include "a.h" + +// Completes definition of Foo +struct Foo { + int val; +}; + +Bar bar_y; diff --git a/cpp/ql/test/library-tests/structs/mutual_recursion/a.c b/cpp/ql/test/library-tests/structs/mutual_recursion/a.c index 6fd3d62ba24..6af982609ad 100644 --- a/cpp/ql/test/library-tests/structs/mutual_recursion/a.c +++ b/cpp/ql/test/library-tests/structs/mutual_recursion/a.c @@ -1,61 +1,61 @@ -struct Node { - struct Node *next; -}; - -struct CompatibleB; -struct CompatibleC; - -struct CompatibleA { - struct CompatibleB *b; -}; - -struct CompatibleB { - struct CompatibleC *c; -}; - -// The 2 definitions of CompatibleC use different but compatible types for x -struct CompatibleC { - struct CompatibleA *a; - int x; -}; - -// The initial handling of recursion didn't catch this case - if you start from -// D, you'll never revisit it, but you will revisit A/B/C. -struct CompatibleD { - struct CompatibleA *a; -}; - -// Ideally, we'd detect that the definitions of Incompatible{A,B} are incompatible, but since their -// fields are pointers, we can't deeply inspect them (it would be possible to have pointers to -// incomplete types that we *can't* deeply inspect). -struct IncompatibleB; -struct IncompatibleC; - -struct IncompatibleA { - struct IncompatibleB *b; -}; - -struct IncompatibleB { - struct IncompatibleC *c; -}; - -// The 2 definitions of IncompatibleC use different and incompatible types for x -struct IncompatibleC { - struct IncompatibleA *a; - short x; -}; - -struct IncompatibleD { - struct IncompatibleA *a; -}; - -// We should be able to detect that the definitions of NonRecursiveA and NonRecursiveB are -// incompatible - unlike the above cases, there's no mutual recursion and no pointer type, so we can -// deeply inspect NonRecursiveA when it's used from NonRecursiveB. -struct NonRecursiveA { - int val; -}; - -struct NonRecursiveB { - struct NonRecursiveA a; -}; +struct Node { + struct Node *next; +}; + +struct CompatibleB; +struct CompatibleC; + +struct CompatibleA { + struct CompatibleB *b; +}; + +struct CompatibleB { + struct CompatibleC *c; +}; + +// The 2 definitions of CompatibleC use different but compatible types for x +struct CompatibleC { + struct CompatibleA *a; + int x; +}; + +// The initial handling of recursion didn't catch this case - if you start from +// D, you'll never revisit it, but you will revisit A/B/C. +struct CompatibleD { + struct CompatibleA *a; +}; + +// Ideally, we'd detect that the definitions of Incompatible{A,B} are incompatible, but since their +// fields are pointers, we can't deeply inspect them (it would be possible to have pointers to +// incomplete types that we *can't* deeply inspect). +struct IncompatibleB; +struct IncompatibleC; + +struct IncompatibleA { + struct IncompatibleB *b; +}; + +struct IncompatibleB { + struct IncompatibleC *c; +}; + +// The 2 definitions of IncompatibleC use different and incompatible types for x +struct IncompatibleC { + struct IncompatibleA *a; + short x; +}; + +struct IncompatibleD { + struct IncompatibleA *a; +}; + +// We should be able to detect that the definitions of NonRecursiveA and NonRecursiveB are +// incompatible - unlike the above cases, there's no mutual recursion and no pointer type, so we can +// deeply inspect NonRecursiveA when it's used from NonRecursiveB. +struct NonRecursiveA { + int val; +}; + +struct NonRecursiveB { + struct NonRecursiveA a; +}; diff --git a/cpp/ql/test/library-tests/structs/mutual_recursion/b.c b/cpp/ql/test/library-tests/structs/mutual_recursion/b.c index 234e1f84e49..1b4d486059a 100644 --- a/cpp/ql/test/library-tests/structs/mutual_recursion/b.c +++ b/cpp/ql/test/library-tests/structs/mutual_recursion/b.c @@ -1,57 +1,57 @@ -struct Node { - struct Node *next; -}; - -struct CompatibleB; -struct CompatibleC; - -struct CompatibleA { - struct CompatibleB *b; -}; - -struct CompatibleB { - struct CompatibleC *c; -}; - -// The 2 definitions of CompatibleC use different but compatible types for x -typedef int AnInt; -struct CompatibleC { - struct CompatibleA *a; - AnInt x; -}; - -struct CompatibleD { - struct CompatibleA *a; -}; - -struct IncompatibleB; -struct IncompatibleC; - -struct IncompatibleA { - struct IncompatibleB *b; -}; - -struct IncompatibleB { - struct IncompatibleC *c; -}; - -// The 2 definitions of IncompatibleC use different and incompatible types for x -struct IncompatibleC { - struct IncompatibleA *a; - int x; -}; - -struct IncompatibleD { - struct IncompatibleA *a; -}; - -// We should be able to detect that the definitions of NonRecursiveA and NonRecursiveB are -// incompatible - unlike the above cases, there's no mutual recursion and no pointer type, so we can -// deeply inspect NonRecursiveA when it's used from NonRecursiveB. -struct NonRecursiveA { - short val; -}; - -struct NonRecursiveB { - struct NonRecursiveA a; -}; +struct Node { + struct Node *next; +}; + +struct CompatibleB; +struct CompatibleC; + +struct CompatibleA { + struct CompatibleB *b; +}; + +struct CompatibleB { + struct CompatibleC *c; +}; + +// The 2 definitions of CompatibleC use different but compatible types for x +typedef int AnInt; +struct CompatibleC { + struct CompatibleA *a; + AnInt x; +}; + +struct CompatibleD { + struct CompatibleA *a; +}; + +struct IncompatibleB; +struct IncompatibleC; + +struct IncompatibleA { + struct IncompatibleB *b; +}; + +struct IncompatibleB { + struct IncompatibleC *c; +}; + +// The 2 definitions of IncompatibleC use different and incompatible types for x +struct IncompatibleC { + struct IncompatibleA *a; + int x; +}; + +struct IncompatibleD { + struct IncompatibleA *a; +}; + +// We should be able to detect that the definitions of NonRecursiveA and NonRecursiveB are +// incompatible - unlike the above cases, there's no mutual recursion and no pointer type, so we can +// deeply inspect NonRecursiveA when it's used from NonRecursiveB. +struct NonRecursiveA { + short val; +}; + +struct NonRecursiveB { + struct NonRecursiveA a; +}; diff --git a/cpp/ql/test/library-tests/structs/qualified_names/c1.cpp b/cpp/ql/test/library-tests/structs/qualified_names/c1.cpp new file mode 100644 index 00000000000..f7230370121 --- /dev/null +++ b/cpp/ql/test/library-tests/structs/qualified_names/c1.cpp @@ -0,0 +1,9 @@ +#include "header.h" + +struct MultipleDefsButSameHeader { + int i; +}; + +struct OneDefInDifferentFile { + int i; +}; diff --git a/cpp/ql/test/library-tests/structs/qualified_names/c2.cpp b/cpp/ql/test/library-tests/structs/qualified_names/c2.cpp new file mode 100644 index 00000000000..be538056615 --- /dev/null +++ b/cpp/ql/test/library-tests/structs/qualified_names/c2.cpp @@ -0,0 +1,6 @@ +#include "header.h" + +struct MultipleDefsButSameHeader { + char char1; + char char2; +}; diff --git a/cpp/ql/test/library-tests/structs/qualified_names/decls.cpp b/cpp/ql/test/library-tests/structs/qualified_names/decls.cpp new file mode 100644 index 00000000000..c6cde7b00b9 --- /dev/null +++ b/cpp/ql/test/library-tests/structs/qualified_names/decls.cpp @@ -0,0 +1,5 @@ +namespace foo { + class C; + + C *x; +} diff --git a/cpp/ql/test/library-tests/structs/qualified_names/defs.cpp b/cpp/ql/test/library-tests/structs/qualified_names/defs.cpp new file mode 100644 index 00000000000..095f8412604 --- /dev/null +++ b/cpp/ql/test/library-tests/structs/qualified_names/defs.cpp @@ -0,0 +1,29 @@ +namespace foo { + class C { + }; +} + +namespace bar { + class C { + }; +} + +class DefinedAndDeclared { +}; + +// Despite this declaration being present, the variable below is associated +// with the definition above rather than this declaration. +class DefinedAndDeclared; + +DefinedAndDeclared *definedAndDeclared; + +#include "header.h" + +// Because there are multiple definitions of `MultipleDefsButSameHeader`, the +// type of this variable will refer to the declaration in `header.h` rather +// than any of the definitions. +MultipleDefsButSameHeader *mdbsh; + +// Because there is only one definition of `OneDefInDifferentFile`, the type of +// this variable will refer to that definition. +OneDefInDifferentFile *odidf; diff --git a/cpp/ql/test/library-tests/structs/qualified_names/header.h b/cpp/ql/test/library-tests/structs/qualified_names/header.h new file mode 100644 index 00000000000..d410b0d3533 --- /dev/null +++ b/cpp/ql/test/library-tests/structs/qualified_names/header.h @@ -0,0 +1,3 @@ +struct MultipleDefsButSameHeader; + +struct OneDefInDifferentFile; diff --git a/cpp/ql/test/library-tests/structs/qualified_names/pointerBaseType.expected b/cpp/ql/test/library-tests/structs/qualified_names/pointerBaseType.expected new file mode 100644 index 00000000000..1573f1c446e --- /dev/null +++ b/cpp/ql/test/library-tests/structs/qualified_names/pointerBaseType.expected @@ -0,0 +1,4 @@ +| decls.cpp:4:6:4:6 | x | decls.cpp:2:9:2:9 | C | +| defs.cpp:18:21:18:38 | definedAndDeclared | defs.cpp:11:7:11:24 | DefinedAndDeclared | +| defs.cpp:25:28:25:32 | mdbsh | header.h:1:8:1:32 | MultipleDefsButSameHeader | +| defs.cpp:29:24:29:28 | odidf | c1.cpp:7:8:7:28 | OneDefInDifferentFile | diff --git a/cpp/ql/test/library-tests/structs/qualified_names/pointerBaseType.ql b/cpp/ql/test/library-tests/structs/qualified_names/pointerBaseType.ql new file mode 100644 index 00000000000..b2aeaee6348 --- /dev/null +++ b/cpp/ql/test/library-tests/structs/qualified_names/pointerBaseType.ql @@ -0,0 +1,5 @@ +import cpp + +from Variable x +where exists(x.getFile().getRelativePath()) +select x, x.getType().(PointerType).getBaseType() diff --git a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.expected b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.expected index 4d2706e2e95..dc73e749a4c 100644 --- a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.expected +++ b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.expected @@ -116,32 +116,13 @@ | isfromtemplateinstantiation.cpp:134:29:134:29 | Outer::operator=(const Outer &) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | | isfromtemplateinstantiation.cpp:134:29:134:29 | declaration of operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | | isfromtemplateinstantiation.cpp:134:29:134:29 | declaration of operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | -| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer::Inner::operator=(Inner &&) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | | isfromtemplateinstantiation.cpp:135:31:135:31 | Outer::Inner::operator=(Inner &&) | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | -| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer::Inner::operator=(const Inner &) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | | isfromtemplateinstantiation.cpp:135:31:135:31 | Outer::Inner::operator=(const Inner &) | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | -| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer::Inner::operator=(Inner &&) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | -| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer::Inner::operator=(Inner &&) | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | -| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer::Inner::operator=(const Inner &) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | -| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer::Inner::operator=(const Inner &) | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | -| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | -| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | | isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | | isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | -| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | -| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | -| isfromtemplateinstantiation.cpp:135:31:135:35 | definition of Inner | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | -| isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | -| isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | | isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | -| isfromtemplateinstantiation.cpp:136:7:136:7 | x | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | -| isfromtemplateinstantiation.cpp:136:7:136:7 | x | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | | isfromtemplateinstantiation.cpp:136:7:136:7 | x | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | -| isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | -| isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | | isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | -| isfromtemplateinstantiation.cpp:137:7:137:7 | y | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | -| isfromtemplateinstantiation.cpp:137:7:137:7 | y | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | | isfromtemplateinstantiation.cpp:137:7:137:7 | y | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | | load.cpp:13:7:13:7 | basic_text_iprimitive::basic_text_iprimitive(basic_text_iprimitive &&) | load.cpp:13:7:13:27 | basic_text_iprimitive | | load.cpp:13:7:13:7 | basic_text_iprimitive::basic_text_iprimitive(const basic_text_iprimitive &) | load.cpp:13:7:13:27 | basic_text_iprimitive | diff --git a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.expected b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.expected index 38fda5364ee..74a096dff1a 100644 --- a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.expected +++ b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.expected @@ -3,6 +3,7 @@ isFromUninstantiatedTemplate | file://:0:0:0:0 | 0 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | | file://:0:0:0:0 | (int)... | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | | file://:0:0:0:0 | (int)... | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | +| file://:0:0:0:0 | Inner | file://:0:0:0:0 | Inner | | file://:0:0:0:0 | declaration of 1st parameter | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | | file://:0:0:0:0 | declaration of 1st parameter | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer | | file://:0:0:0:0 | initializer for MyClassEnumConst | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | @@ -433,15 +434,15 @@ isFromUninstantiatedTemplate | isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | I | T | DeclarationEntry | | | isfromtemplateinstantiation.cpp:135:31:135:31 | operator= | I | T | Declaration | | | isfromtemplateinstantiation.cpp:135:31:135:31 | operator= | I | T | Declaration | | -| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | I | T | Declaration | | +| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | | T | Declaration | | | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner | I | T | Declaration | | +| isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | | T | Definition | | | isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | I | T | Definition | | -| isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | I | T | Definition | | -| isfromtemplateinstantiation.cpp:136:7:136:7 | x | I | T | Declaration | | +| isfromtemplateinstantiation.cpp:136:7:136:7 | x | | T | Declaration | | | isfromtemplateinstantiation.cpp:136:7:136:7 | x | I | T | Declaration | | +| isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | | T | Definition | | | isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | I | T | Definition | | -| isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | I | T | Definition | | -| isfromtemplateinstantiation.cpp:137:7:137:7 | y | I | T | Declaration | | +| isfromtemplateinstantiation.cpp:137:7:137:7 | y | | T | Declaration | | | isfromtemplateinstantiation.cpp:137:7:137:7 | y | I | T | Declaration | | | isfromtemplateinstantiation.cpp:144:28:144:56 | incomplete_never_instantiated | | T | Declaration | | | isfromtemplateinstantiation.cpp:146:28:146:45 | never_instantiated | | T | Declaration | | diff --git a/cpp/ql/test/library-tests/typedefs/typedefs.cpp b/cpp/ql/test/library-tests/typedefs/typedefs.cpp index 37043e5cf46..6998b6c8ef7 100644 --- a/cpp/ql/test/library-tests/typedefs/typedefs.cpp +++ b/cpp/ql/test/library-tests/typedefs/typedefs.cpp @@ -1,31 +1,31 @@ -namespace NS1 -{ - typedef int WIDTH; -} - -void f1() -{ - typedef int TYPE; - class D {}; -} - -class A -{ - -protected: - typedef NS1::WIDTH WIDTH; - typedef WIDTH WIDTH2; - -public: - typedef WIDTH WIDTH3; - -private: - typedef WIDTH WIDTH4; -}; - -class B: public A { - WIDTH i; - WIDTH2 i2; - WIDTH3 i3; - //WIDTH4 i4; --- inaccessible -}; +namespace NS1 +{ + typedef int WIDTH; +} + +void f1() +{ + typedef int TYPE; + class D {}; +} + +class A +{ + +protected: + typedef NS1::WIDTH WIDTH; + typedef WIDTH WIDTH2; + +public: + typedef WIDTH WIDTH3; + +private: + typedef WIDTH WIDTH4; +}; + +class B: public A { + WIDTH i; + WIDTH2 i2; + WIDTH3 i3; + //WIDTH4 i4; --- inaccessible +}; diff --git a/cpp/ql/test/library-tests/typename/typename.expected b/cpp/ql/test/library-tests/typename/typename.expected index 09bff6e139e..31a76b90ab2 100644 --- a/cpp/ql/test/library-tests/typename/typename.expected +++ b/cpp/ql/test/library-tests/typename/typename.expected @@ -1,4 +1,4 @@ -| file://:0:0:0:0 | T | -| file://:0:0:0:0 | int | -| file://:0:0:0:0 | myClass | -| file://:0:0:0:0 | short | +| file://:0:0:0:0 | T | +| file://:0:0:0:0 | int | +| file://:0:0:0:0 | myClass | +| file://:0:0:0:0 | short | diff --git a/cpp/ql/test/library-tests/types/__wchar_t/options b/cpp/ql/test/library-tests/types/__wchar_t/options index 8ee3fcb9163..c3fc566fda2 100644 --- a/cpp/ql/test/library-tests/types/__wchar_t/options +++ b/cpp/ql/test/library-tests/types/__wchar_t/options @@ -1 +1 @@ -semmle-extractor-options: --microsoft +semmle-extractor-options: --microsoft diff --git a/cpp/ql/test/library-tests/types/integral_types_ms/integral_types.cpp b/cpp/ql/test/library-tests/types/integral_types_ms/integral_types.cpp index aab2fa52924..cacb48b3b8c 100644 --- a/cpp/ql/test/library-tests/types/integral_types_ms/integral_types.cpp +++ b/cpp/ql/test/library-tests/types/integral_types_ms/integral_types.cpp @@ -1,5 +1,5 @@ - -__int8 i8; -__int16 i16; -__int32 i32; -__int64 i64; + +__int8 i8; +__int16 i16; +__int32 i32; +__int64 i64; diff --git a/cpp/ql/test/library-tests/types/integral_types_ms/options b/cpp/ql/test/library-tests/types/integral_types_ms/options index 3eadeb8d45a..668c53efd7d 100644 --- a/cpp/ql/test/library-tests/types/integral_types_ms/options +++ b/cpp/ql/test/library-tests/types/integral_types_ms/options @@ -1 +1 @@ -semmle-extractor-options: --microsoft --edg --target --edg win64 +semmle-extractor-options: --microsoft --edg --target --edg win64 diff --git a/cpp/ql/test/library-tests/types/pointertypes/pointertypes.c b/cpp/ql/test/library-tests/types/pointertypes/pointertypes.c index 2881dc87853..65bca5fa9da 100644 --- a/cpp/ql/test/library-tests/types/pointertypes/pointertypes.c +++ b/cpp/ql/test/library-tests/types/pointertypes/pointertypes.c @@ -1,40 +1,40 @@ - -char c; -char *cp; - -const char cc; -char const cc2; -const char *ccp; -char const *ccp2; -char * const ccp3; -char const * const ccp4; - -volatile char vc; -char volatile vc2; -volatile char *vcp; -char volatile *vcp2; -char * volatile vcp3; -char volatile * volatile vcp4; - -char * restrict rcp; -char *__restrict__ rcp2; - -void *vp; - -const void *cvp; -void const *cvp2; -void * const cvp3; -void const * const cvp4; - -void *restrict rvp1; -void *__restrict__ rvp2; - -const struct s *csp; -struct s const *csp2; -struct s * const csp3; -struct s const * const csp4; - -struct s *restrict rsp1; -struct s *__restrict__ rsp2; - -char * const volatile restrict cvrcp; + +char c; +char *cp; + +const char cc; +char const cc2; +const char *ccp; +char const *ccp2; +char * const ccp3; +char const * const ccp4; + +volatile char vc; +char volatile vc2; +volatile char *vcp; +char volatile *vcp2; +char * volatile vcp3; +char volatile * volatile vcp4; + +char * restrict rcp; +char *__restrict__ rcp2; + +void *vp; + +const void *cvp; +void const *cvp2; +void * const cvp3; +void const * const cvp4; + +void *restrict rvp1; +void *__restrict__ rvp2; + +const struct s *csp; +struct s const *csp2; +struct s * const csp3; +struct s const * const csp4; + +struct s *restrict rsp1; +struct s *__restrict__ rsp2; + +char * const volatile restrict cvrcp; diff --git a/cpp/ql/test/library-tests/types/refersTo/refersTo.cpp b/cpp/ql/test/library-tests/types/refersTo/refersTo.cpp index 05564ae604b..8a277a1d753 100644 --- a/cpp/ql/test/library-tests/types/refersTo/refersTo.cpp +++ b/cpp/ql/test/library-tests/types/refersTo/refersTo.cpp @@ -1,20 +1,20 @@ - -class a -{ -}; - -typedef a &a_ref; -typedef a *a_ptr; -typedef a a_array[10]; - -template -class container -{ -public: - T t; -}; - -class strange : public container > -{ -public: -}; + +class a +{ +}; + +typedef a &a_ref; +typedef a *a_ptr; +typedef a a_array[10]; + +template +class container +{ +public: + T t; +}; + +class strange : public container > +{ +public: +}; diff --git a/cpp/ql/test/library-tests/types/scope/scope.cpp b/cpp/ql/test/library-tests/types/scope/scope.cpp index c9d0d962d62..2a7b6501d3f 100644 --- a/cpp/ql/test/library-tests/types/scope/scope.cpp +++ b/cpp/ql/test/library-tests/types/scope/scope.cpp @@ -1,27 +1,27 @@ - -int a[100]; -typedef int my_array[200]; - -void g1(int b[300]); -void g1(int b[300]) { - int c[400]; - - typedef int my_array_2[500]; - my_array d; - my_array_2 e; - - class f - { - public: - void g2() - { - int g[600]; - } - - int h[700]; - }; - - int i = sizeof(int[800]); - auto j = new int[900]; - int *k = new int[1000]; -} + +int a[100]; +typedef int my_array[200]; + +void g1(int b[300]); +void g1(int b[300]) { + int c[400]; + + typedef int my_array_2[500]; + my_array d; + my_array_2 e; + + class f + { + public: + void g2() + { + int g[600]; + } + + int h[700]; + }; + + int i = sizeof(int[800]); + auto j = new int[900]; + int *k = new int[1000]; +} diff --git a/cpp/ql/test/library-tests/types/types/types.cpp b/cpp/ql/test/library-tests/types/types/types.cpp index ab811aea829..903ede7c49b 100644 --- a/cpp/ql/test/library-tests/types/types/types.cpp +++ b/cpp/ql/test/library-tests/types/types/types.cpp @@ -1,82 +1,82 @@ -extern int i; - -const int c = 7; -const double pi = 3.1415926535897932385; - -unsigned a; - -unsigned int b; - -typedef char* Pchar; - -const char* kings[] = { "Antigonus", "Seleucus", "Ptolemy" }; - -int* p, q; -int v1[10], *pv; - -int (*fp)(char *); // pointer to function - -float v2[3]; -char* v3[32]; - -int d2[10][20]; - -char v4[3] = { 'a', 'b', 0 }; - -int v5[8] = { 1, 2, 3, 4 }; - -char* p2 = "Plato"; -char p3[] = "Zeno"; - -char alpha[] = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -int av[] = { 1, 2 , 3, 4 }; -int* ap1 = av; -int* ap2 = &av[0]; -int* ap3 = &av[4]; - -int f(int* pi) -{ - void* pv = pi; - return 0; -} - -void f1(char* p) -{ - char s[] = "Gorm"; - const char* pc = s; - pc = p; - - char *const cp = s; - cp[3] = 'a'; - - const char *const cpc = s; - char const* pc2 = s; -} - -void f2() -{ - int i = 1; - int& r = i; - int x = r; - r = 2; - const double& cdr = 1; -} - -void increment(int& aa) { aa++; } - -__int128 i128; -signed __int128 i128s; -unsigned __int128 i128u; - -Pchar pchar; - -typedef unsigned long size_t; -typedef long ssize_t; -typedef long ptrdiff_t; - -size_t st; -ssize_t sst; -ptrdiff_t pdt; -wchar_t wct; +extern int i; + +const int c = 7; +const double pi = 3.1415926535897932385; + +unsigned a; + +unsigned int b; + +typedef char* Pchar; + +const char* kings[] = { "Antigonus", "Seleucus", "Ptolemy" }; + +int* p, q; +int v1[10], *pv; + +int (*fp)(char *); // pointer to function + +float v2[3]; +char* v3[32]; + +int d2[10][20]; + +char v4[3] = { 'a', 'b', 0 }; + +int v5[8] = { 1, 2, 3, 4 }; + +char* p2 = "Plato"; +char p3[] = "Zeno"; + +char alpha[] = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +int av[] = { 1, 2 , 3, 4 }; +int* ap1 = av; +int* ap2 = &av[0]; +int* ap3 = &av[4]; + +int f(int* pi) +{ + void* pv = pi; + return 0; +} + +void f1(char* p) +{ + char s[] = "Gorm"; + const char* pc = s; + pc = p; + + char *const cp = s; + cp[3] = 'a'; + + const char *const cpc = s; + char const* pc2 = s; +} + +void f2() +{ + int i = 1; + int& r = i; + int x = r; + r = 2; + const double& cdr = 1; +} + +void increment(int& aa) { aa++; } + +__int128 i128; +signed __int128 i128s; +unsigned __int128 i128u; + +Pchar pchar; + +typedef unsigned long size_t; +typedef long ssize_t; +typedef long ptrdiff_t; + +size_t st; +ssize_t sst; +ptrdiff_t pdt; +wchar_t wct; diff --git a/cpp/ql/test/library-tests/types/wchar_t_typedef/ms.c b/cpp/ql/test/library-tests/types/wchar_t_typedef/ms.c index e1c0bcc4c4a..f8c5cf9d2fa 100644 --- a/cpp/ql/test/library-tests/types/wchar_t_typedef/ms.c +++ b/cpp/ql/test/library-tests/types/wchar_t_typedef/ms.c @@ -1,4 +1,4 @@ - -typedef unsigned short wchar_t; - -wchar_t *wstring; + +typedef unsigned short wchar_t; + +wchar_t *wstring; diff --git a/cpp/ql/test/library-tests/types/wchar_t_typedef/options b/cpp/ql/test/library-tests/types/wchar_t_typedef/options index b1ef636d3e9..979872636a4 100644 --- a/cpp/ql/test/library-tests/types/wchar_t_typedef/options +++ b/cpp/ql/test/library-tests/types/wchar_t_typedef/options @@ -1 +1 @@ -semmle-extractor-options: --microsoft --edg --target --edg win32 +semmle-extractor-options: --microsoft --edg --target --edg win32 diff --git a/cpp/ql/test/library-tests/unions/unions.cpp b/cpp/ql/test/library-tests/unions/unions.cpp index 6122c4e379d..a693e3bc9d8 100644 --- a/cpp/ql/test/library-tests/unions/unions.cpp +++ b/cpp/ql/test/library-tests/unions/unions.cpp @@ -1,23 +1,23 @@ - -enum Type { S, I }; - -struct Entry { - - char* name; - Type t; - char* s; - int i; - -}; - -union Value { - char* s; - int i; -}; - - -struct EntryWithMethod: Entry { - int getAsInt() { - return i; - } -}; + +enum Type { S, I }; + +struct Entry { + + char* name; + Type t; + char* s; + int i; + +}; + +union Value { + char* s; + int i; +}; + + +struct EntryWithMethod: Entry { + int getAsInt() { + return i; + } +}; diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp index 2003a299aab..d18ffed10ea 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/test.cpp @@ -93,15 +93,15 @@ int regression_test00() { return x; } -struct Base { +struct Base { int b; }; -struct Derived : Base { +struct Derived : Base { int d; }; -int inheritanceConversions(Derived* pd) { +int inheritanceConversions(Derived* pd) { int x = pd->b; Base* pb = static_cast(pd); int y = pb->b; diff --git a/cpp/ql/test/library-tests/variables/variables/variables.cpp b/cpp/ql/test/library-tests/variables/variables/variables.cpp index 28aae674374..cbca2b3b822 100644 --- a/cpp/ql/test/library-tests/variables/variables/variables.cpp +++ b/cpp/ql/test/library-tests/variables/variables/variables.cpp @@ -1,53 +1,53 @@ -extern int i; -extern int i; -extern int i; - -const int c = 7; -const double pi = 3.1415926535897932385; - -unsigned a; - -unsigned int b; - -const char* kings[] = { "Antigonus", "Seleucus", "Ptolemy" }; - -int* p, q; -static int v1[10], *pv; - -int (*fp)(char *); // pointer to function - -float v2[3]; -char* v3[32]; - -int d2[10][20]; - -char v4[3] = { 'a', 'b', 0 }; - -int v5[8] = { 1, 2, 3, 4 }; - -char* p2 = "Plato"; -char p3[] = "Zeno"; - -char alpha[] = "abcdefghijklmnopqrstuvwxyz" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -int av[] = { 1, 2 , 3, 4 }; -int* ap1 = av; -int* ap2 = &av[0]; -int* ap3 = &av[4]; - - -void f() { - char local[] = { 'a', 'b' }; - { - static int local; - } -} - -struct address { - char* name; - long int number; - char* street; - char* town; - static char* country; -}; +extern int i; +extern int i; +extern int i; + +const int c = 7; +const double pi = 3.1415926535897932385; + +unsigned a; + +unsigned int b; + +const char* kings[] = { "Antigonus", "Seleucus", "Ptolemy" }; + +int* p, q; +static int v1[10], *pv; + +int (*fp)(char *); // pointer to function + +float v2[3]; +char* v3[32]; + +int d2[10][20]; + +char v4[3] = { 'a', 'b', 0 }; + +int v5[8] = { 1, 2, 3, 4 }; + +char* p2 = "Plato"; +char p3[] = "Zeno"; + +char alpha[] = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +int av[] = { 1, 2 , 3, 4 }; +int* ap1 = av; +int* ap2 = &av[0]; +int* ap3 = &av[4]; + + +void f() { + char local[] = { 'a', 'b' }; + { + static int local; + } +} + +struct address { + char* name; + long int number; + char* street; + char* town; + static char* country; +}; diff --git a/cpp/ql/test/library-tests/virtual_functions/virtual_functions/virtual_functions.cpp b/cpp/ql/test/library-tests/virtual_functions/virtual_functions/virtual_functions.cpp index 2ecea309538..61a4e4ec545 100644 --- a/cpp/ql/test/library-tests/virtual_functions/virtual_functions/virtual_functions.cpp +++ b/cpp/ql/test/library-tests/virtual_functions/virtual_functions/virtual_functions.cpp @@ -1,48 +1,48 @@ -class A -{ -public: - virtual void withunusedpara(int * para1, int unusedpara) = 0; - virtual void withunusedpara(int * para1, int & para2) = 0; -}; - -class B1: public A -{ -public: - virtual void withunusedpara(int * para1, int unusedpara) - { - *para1 = 1U; - } - virtual void withunusedpara(int * para1, int & para2) - { - *para1 = 1U; - } -}; - -class B2: public A -{ -public: - virtual void withunusedpara(int * para1, int unusedpara) - { - *para1 = 1U; - } - virtual void withunusedpara(int * para1, int & para2) - { - para2 = 0; - } -}; - -struct X1 { virtual void f() {} }; -struct X2 : X1 {}; -struct X3 : X2 { void f() {} }; -struct X4 : X2 { void f() {} }; -struct X5 : X3, X4 { void f() {} }; -struct X6 : X5 {}; -struct X7 : X6 { void f() {} }; - -struct Y1 { virtual void f() {} }; -struct Y2 : Y1 {}; -struct Y3 : virtual Y2 { void f() {} }; -struct Y4 : virtual Y2 { void f() {} }; -struct Y5 : Y3, Y4 { void f() {} }; -struct Y6 : Y5 {}; -struct Y7 : Y6 { void f() {} }; +class A +{ +public: + virtual void withunusedpara(int * para1, int unusedpara) = 0; + virtual void withunusedpara(int * para1, int & para2) = 0; +}; + +class B1: public A +{ +public: + virtual void withunusedpara(int * para1, int unusedpara) + { + *para1 = 1U; + } + virtual void withunusedpara(int * para1, int & para2) + { + *para1 = 1U; + } +}; + +class B2: public A +{ +public: + virtual void withunusedpara(int * para1, int unusedpara) + { + *para1 = 1U; + } + virtual void withunusedpara(int * para1, int & para2) + { + para2 = 0; + } +}; + +struct X1 { virtual void f() {} }; +struct X2 : X1 {}; +struct X3 : X2 { void f() {} }; +struct X4 : X2 { void f() {} }; +struct X5 : X3, X4 { void f() {} }; +struct X6 : X5 {}; +struct X7 : X6 { void f() {} }; + +struct Y1 { virtual void f() {} }; +struct Y2 : Y1 {}; +struct Y3 : virtual Y2 { void f() {} }; +struct Y4 : virtual Y2 { void f() {} }; +struct Y5 : Y3, Y4 { void f() {} }; +struct Y6 : Y5 {}; +struct Y7 : Y6 { void f() {} }; diff --git a/cpp/ql/test/query-tests/AlertSuppression/.gitattributes b/cpp/ql/test/query-tests/AlertSuppression/.gitattributes new file mode 100644 index 00000000000..ba9355dd601 --- /dev/null +++ b/cpp/ql/test/query-tests/AlertSuppression/.gitattributes @@ -0,0 +1 @@ +tstWindows.c eol=crlf diff --git a/cpp/ql/test/query-tests/AlertSuppression/tstWindows.c b/cpp/ql/test/query-tests/AlertSuppression/tstWindows.c index ee53d91dd79..a669e765981 100644 --- a/cpp/ql/test/query-tests/AlertSuppression/tstWindows.c +++ b/cpp/ql/test/query-tests/AlertSuppression/tstWindows.c @@ -1,28 +1,28 @@ -int x = 0; // lgtm -// lgtm[js/debugger-statement] -// lgtm[js/debugger-statement, js/invocation-of-non-function] -// lgtm[@tag:nullness] -// lgtm[@tag:nullness,js/debugger-statement] -// lgtm[@expires:2017-06-11] -// lgtm[js/invocation-of-non-function] because I know better than lgtm -// lgtm: blah blah -// lgtm blah blah #falsepositive -//lgtm [js/invocation-of-non-function] -/* lgtm */ -// lgtm[] -// lgtmfoo -//lgtm -// lgtm -// lgtm [js/debugger-statement] -// foolgtm[js/debugger-statement] -// foolgtm -// foo; lgtm -// foo; lgtm[js/debugger-statement] -// foo lgtm -// foo lgtm[js/debugger-statement] -// foo lgtm bar -// foo lgtm[js/debugger-statement] bar -// LGTM! -// LGTM[js/debugger-statement] -// lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] -// lgtm[js/debugger-statement]; lgtm +int x = 0; // lgtm +// lgtm[js/debugger-statement] +// lgtm[js/debugger-statement, js/invocation-of-non-function] +// lgtm[@tag:nullness] +// lgtm[@tag:nullness,js/debugger-statement] +// lgtm[@expires:2017-06-11] +// lgtm[js/invocation-of-non-function] because I know better than lgtm +// lgtm: blah blah +// lgtm blah blah #falsepositive +//lgtm [js/invocation-of-non-function] +/* lgtm */ +// lgtm[] +// lgtmfoo +//lgtm +// lgtm +// lgtm [js/debugger-statement] +// foolgtm[js/debugger-statement] +// foolgtm +// foo; lgtm +// foo; lgtm[js/debugger-statement] +// foo lgtm +// foo lgtm[js/debugger-statement] +// foo lgtm bar +// foo lgtm[js/debugger-statement] bar +// LGTM! +// LGTM[js/debugger-statement] +// lgtm[js/debugger-statement] and lgtm[js/invocation-of-non-function] +// lgtm[js/debugger-statement]; lgtm diff --git a/cpp/ql/test/query-tests/Best Practices/Magic Constants/MagicConstantsNumbers/functions.h b/cpp/ql/test/query-tests/Best Practices/Magic Constants/MagicConstantsNumbers/functions.h index 31201fb5c11..43e7b089389 100644 --- a/cpp/ql/test/query-tests/Best Practices/Magic Constants/MagicConstantsNumbers/functions.h +++ b/cpp/ql/test/query-tests/Best Practices/Magic Constants/MagicConstantsNumbers/functions.h @@ -1,33 +1,33 @@ - -int myFunction1(int x = - 102 + 102 + 102 + - 102 + 102 + 102 + - 102 + 102 + 102 + - 102 + 102 + 102 + - 102 + 102 + 102 + - 102 + 102 + 102 + - 102 + 102 + 102); - -void myFunction2( - int p1 = 103, - int p2 = 103, - int p3 = 103, - int p4 = 103, - int p5 = 103, - int p6 = 103, - int p7 = 103, - int p8 = 103, - int p9 = 103, - int p10 = 103, - int p11 = 103, - int p12 = 103, - int p13 = 103, - int p14 = 103, - int p15 = 103, - int p16 = 103, - int p17 = 103, - int p18 = 103, - int p19 = 103, - int p20 = 103, - int p21 = 103 - ) {}; + +int myFunction1(int x = + 102 + 102 + 102 + + 102 + 102 + 102 + + 102 + 102 + 102 + + 102 + 102 + 102 + + 102 + 102 + 102 + + 102 + 102 + 102 + + 102 + 102 + 102); + +void myFunction2( + int p1 = 103, + int p2 = 103, + int p3 = 103, + int p4 = 103, + int p5 = 103, + int p6 = 103, + int p7 = 103, + int p8 = 103, + int p9 = 103, + int p10 = 103, + int p11 = 103, + int p12 = 103, + int p13 = 103, + int p14 = 103, + int p15 = 103, + int p16 = 103, + int p17 = 103, + int p18 = 103, + int p19 = 103, + int p20 = 103, + int p21 = 103 + ) {}; diff --git a/cpp/ql/test/query-tests/Best Practices/Magic Constants/MagicConstantsNumbers/test.cpp b/cpp/ql/test/query-tests/Best Practices/Magic Constants/MagicConstantsNumbers/test.cpp index 3e331dbb34c..268cb4e91c9 100644 --- a/cpp/ql/test/query-tests/Best Practices/Magic Constants/MagicConstantsNumbers/test.cpp +++ b/cpp/ql/test/query-tests/Best Practices/Magic Constants/MagicConstantsNumbers/test.cpp @@ -1,14 +1,14 @@ - -#include "functions.h" - -int myFunction1(int x) { - return x; -} - -void myCaller() { - myFunction1(); - myFunction1(); - myFunction1(104); - myFunction2(105); - myFunction2(); + +#include "functions.h" + +int myFunction1(int x) { + return x; +} + +void myCaller() { + myFunction1(); + myFunction1(); + myFunction1(104); + myFunction2(105); + myFunction2(); } \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/a.h b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/a.h index a0da4edfc5e..6addf5ae76d 100644 --- a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/a.h +++ b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/a.h @@ -1,3 +1,3 @@ -// a.h - -int my_func_a(); +// a.h + +int my_func_a(); diff --git a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/b.h b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/b.h index 55666fde62e..e9f8542fdf5 100644 --- a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/b.h +++ b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/b.h @@ -1,3 +1,3 @@ -// b.h - -int my_func_b(); +// b.h + +int my_func_b(); diff --git a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/c.h b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/c.h index dfae8989d79..f4054f52983 100644 --- a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/c.h +++ b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/c.h @@ -1,3 +1,3 @@ -// c.h - -extern int my_var_c; +// c.h + +extern int my_var_c; diff --git a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/d.hpp b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/d.hpp index 1a53af694b8..ddb004892b5 100644 --- a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/d.hpp +++ b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/d.hpp @@ -1,3 +1,3 @@ -// d.hpp - -class class_d; +// d.hpp + +class class_d; diff --git a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/e.hpp b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/e.hpp index 814c86a34cf..f75c2430d0e 100644 --- a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/e.hpp +++ b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/e.hpp @@ -1,3 +1,3 @@ -// e.hpp - -class class_e; +// e.hpp + +class class_e; diff --git a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/f.fwd.hpp b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/f.fwd.hpp index 1eebacaf324..ace4a0b7082 100644 --- a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/f.fwd.hpp +++ b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/f.fwd.hpp @@ -1,3 +1,3 @@ -// f.fwd.hpp - -class class_f; +// f.fwd.hpp + +class class_f; diff --git a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/g b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/g index c3076bdfb82..7d808bf9b83 100644 --- a/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/g +++ b/cpp/ql/test/query-tests/Best Practices/Unused Entities/UnusedIncludes/g @@ -1 +1 @@ -// g +// g diff --git a/cpp/ql/test/query-tests/Critical/NewFree/options b/cpp/ql/test/query-tests/Critical/NewFree/options index 8ee3fcb9163..c3fc566fda2 100644 --- a/cpp/ql/test/query-tests/Critical/NewFree/options +++ b/cpp/ql/test/query-tests/Critical/NewFree/options @@ -1 +1 @@ -semmle-extractor-options: --microsoft +semmle-extractor-options: --microsoft diff --git a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header1.h b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header1.h index ab3226d8e65..a0fa07dbb50 100644 --- a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header1.h +++ b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header1.h @@ -1,8 +1,8 @@ -// header1.h - -#ifndef INCLUDED_HEADER1 -#define INCLUDED_HEADER1 - - // ... - -#endif // INCLUDED_HEADER1 +// header1.h + +#ifndef INCLUDED_HEADER1 +#define INCLUDED_HEADER1 + + // ... + +#endif // INCLUDED_HEADER1 diff --git a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header2.h b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header2.h index f9f62cc8d75..9e4ad972812 100644 --- a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header2.h +++ b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header2.h @@ -1,8 +1,8 @@ -// header2.h - -#ifndef INCLUDED_HEADER1 // oops! -#define INCLUDED_HEADER1 - - // ... - -#endif // INCLUDED_HEADER1 +// header2.h + +#ifndef INCLUDED_HEADER1 // oops! +#define INCLUDED_HEADER1 + + // ... + +#endif // INCLUDED_HEADER1 diff --git a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header3.h b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header3.h index 789c3354309..ed4e1e65dde 100644 --- a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header3.h +++ b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header3.h @@ -1,12 +1,12 @@ -// header3.h - -#ifndef INCLUDED_HEADER3 -#define INCLUDED_HEADER3 - - // ... - - #ifndef INCLUDED_HEADER1 // (not an include guard) - - #endif - -#endif // INCLUDED_HEADER3 +// header3.h + +#ifndef INCLUDED_HEADER3 +#define INCLUDED_HEADER3 + + // ... + + #ifndef INCLUDED_HEADER1 // (not an include guard) + + #endif + +#endif // INCLUDED_HEADER3 diff --git a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header4.h b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header4.h index 6c990c74aa4..57b36896ebd 100644 --- a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header4.h +++ b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header4.h @@ -1,8 +1,8 @@ -// header4.h - -#ifndef INCLUDED_HEADER4 -#define INCLUDED_HEADER4 - - // ... - -#endif // INCLUDED_HEADER4 +// header4.h + +#ifndef INCLUDED_HEADER4 +#define INCLUDED_HEADER4 + + // ... + +#endif // INCLUDED_HEADER4 diff --git a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header6.h b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header6.h index c8a1a968f18..2148e608917 100644 --- a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header6.h +++ b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header6.h @@ -1,8 +1,8 @@ -// header6.h - -#ifndef INCLUDED_HEADER6 -#define INCLUDED_HEADER6 - - // ... - -#endif // INCLUDED_HEADER6 +// header6.h + +#ifndef INCLUDED_HEADER6 +#define INCLUDED_HEADER6 + + // ... + +#endif // INCLUDED_HEADER6 diff --git a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header7.h b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header7.h index 0687d80c60c..4dd8875d69d 100644 --- a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header7.h +++ b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/header7.h @@ -1,8 +1,8 @@ -// header7.h - -#ifndef INCLUDED_HEADER6 // oops! -#define INCLUDED_HEADER6(x) (x) - - // ... - -#endif // INCLUDED_HEADER6 +// header7.h + +#ifndef INCLUDED_HEADER6 // oops! +#define INCLUDED_HEADER6(x) (x) + + // ... + +#endif // INCLUDED_HEADER6 diff --git a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/main.c b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/main.c index 40cbdbb9443..0736e1517ef 100644 --- a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/main.c +++ b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/main.c @@ -1,13 +1,13 @@ -// main.c - Cleanup-DuplicateIncludeGuard test - -#include "header1.h" -#include "header2.h" -#include "header3.h" -#include "header3.h" - -#include "header4.h" -#include "subfolder/header4.h" -#include "subfolder/header5.h" - -#include "header6.h" -#include "header7.h" +// main.c - Cleanup-DuplicateIncludeGuard test + +#include "header1.h" +#include "header2.h" +#include "header3.h" +#include "header3.h" + +#include "header4.h" +#include "subfolder/header4.h" +#include "subfolder/header5.h" + +#include "header6.h" +#include "header7.h" diff --git a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/subfolder/header4.h b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/subfolder/header4.h index f369cf90544..c5e44813dcd 100644 --- a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/subfolder/header4.h +++ b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/subfolder/header4.h @@ -1,8 +1,8 @@ -// header4.h - -#ifndef INCLUDED_HEADER4 // duplicate -#define INCLUDED_HEADER4 - - // ... - -#endif // INCLUDED_HEADER4 +// header4.h + +#ifndef INCLUDED_HEADER4 // duplicate +#define INCLUDED_HEADER4 + + // ... + +#endif // INCLUDED_HEADER4 diff --git a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/subfolder/header5.h b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/subfolder/header5.h index 2f89436d7a8..ed54e7ea68c 100644 --- a/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/subfolder/header5.h +++ b/cpp/ql/test/query-tests/Header Cleanup/Cleanup-DuplicateIncludeGuard/subfolder/header5.h @@ -1,8 +1,8 @@ -// header5.h - -#ifndef INCLUDED_HEADER4 // duplicate -#define INCLUDED_HEADER4 - - // ... - -#endif // INCLUDED_HEADER4 +// header5.h + +#ifndef INCLUDED_HEADER4 // duplicate +#define INCLUDED_HEADER4 + + // ... + +#endif // INCLUDED_HEADER4 diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/IntMultToLong/IntMultToLong.c b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/IntMultToLong/IntMultToLong.c index 603fd50b774..76ab0e83c59 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/IntMultToLong/IntMultToLong.c +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/IntMultToLong/IntMultToLong.c @@ -88,3 +88,7 @@ void use_printf(float f, double d) // ^ there's a float -> double varargs promotion here, but it's unlikely that the author anticipates requiring a double printf("%f", d * d); // safe } + +size_t three_chars(unsigned char a, unsigned char b, unsigned char c) { + return a * b * c; // at most 16581375 +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/common.h b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/common.h index baffbb6f36f..8dda6a8a8d3 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/common.h +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_signed_chars/common.h @@ -1,20 +1,20 @@ - -struct _IO_FILE -{ - // ... -}; -typedef struct _IO_FILE FILE; - -#define va_list void * -#define va_start(x, y) -#define va_end(x) - -extern int printf(const char *fmt, ...); -extern int vprintf(const char *fmt, va_list ap); -extern int vfprintf(FILE *stream, const char *format, va_list ap); - -#include "printf1.h" -#include "real_world.h" -#include "wide_string.h" -#include "format.h" -#include "pri_macros.h" + +struct _IO_FILE +{ + // ... +}; +typedef struct _IO_FILE FILE; + +#define va_list void * +#define va_start(x, y) +#define va_end(x) + +extern int printf(const char *fmt, ...); +extern int vprintf(const char *fmt, va_list ap); +extern int vfprintf(FILE *stream, const char *format, va_list ap); + +#include "printf1.h" +#include "real_world.h" +#include "wide_string.h" +#include "format.h" +#include "pri_macros.h" diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/common.h b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/common.h index baffbb6f36f..8dda6a8a8d3 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/common.h +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Linux_unsigned_chars/common.h @@ -1,20 +1,20 @@ - -struct _IO_FILE -{ - // ... -}; -typedef struct _IO_FILE FILE; - -#define va_list void * -#define va_start(x, y) -#define va_end(x) - -extern int printf(const char *fmt, ...); -extern int vprintf(const char *fmt, va_list ap); -extern int vfprintf(FILE *stream, const char *format, va_list ap); - -#include "printf1.h" -#include "real_world.h" -#include "wide_string.h" -#include "format.h" -#include "pri_macros.h" + +struct _IO_FILE +{ + // ... +}; +typedef struct _IO_FILE FILE; + +#define va_list void * +#define va_start(x, y) +#define va_end(x) + +extern int printf(const char *fmt, ...); +extern int vprintf(const char *fmt, va_list ap); +extern int vfprintf(FILE *stream, const char *format, va_list ap); + +#include "printf1.h" +#include "real_world.h" +#include "wide_string.h" +#include "format.h" +#include "pri_macros.h" diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/common.h b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/common.h index baffbb6f36f..8dda6a8a8d3 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/common.h +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft/common.h @@ -1,20 +1,20 @@ - -struct _IO_FILE -{ - // ... -}; -typedef struct _IO_FILE FILE; - -#define va_list void * -#define va_start(x, y) -#define va_end(x) - -extern int printf(const char *fmt, ...); -extern int vprintf(const char *fmt, va_list ap); -extern int vfprintf(FILE *stream, const char *format, va_list ap); - -#include "printf1.h" -#include "real_world.h" -#include "wide_string.h" -#include "format.h" -#include "pri_macros.h" + +struct _IO_FILE +{ + // ... +}; +typedef struct _IO_FILE FILE; + +#define va_list void * +#define va_start(x, y) +#define va_end(x) + +extern int printf(const char *fmt, ...); +extern int vprintf(const char *fmt, va_list ap); +extern int vfprintf(FILE *stream, const char *format, va_list ap); + +#include "printf1.h" +#include "real_world.h" +#include "wide_string.h" +#include "format.h" +#include "pri_macros.h" diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/common.h b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/common.h index baffbb6f36f..8dda6a8a8d3 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/common.h +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/WrongTypeFormatArguments/Microsoft_no_wchar/common.h @@ -1,20 +1,20 @@ - -struct _IO_FILE -{ - // ... -}; -typedef struct _IO_FILE FILE; - -#define va_list void * -#define va_start(x, y) -#define va_end(x) - -extern int printf(const char *fmt, ...); -extern int vprintf(const char *fmt, va_list ap); -extern int vfprintf(FILE *stream, const char *format, va_list ap); - -#include "printf1.h" -#include "real_world.h" -#include "wide_string.h" -#include "format.h" -#include "pri_macros.h" + +struct _IO_FILE +{ + // ... +}; +typedef struct _IO_FILE FILE; + +#define va_list void * +#define va_start(x, y) +#define va_end(x) + +extern int printf(const char *fmt, ...); +extern int vprintf(const char *fmt, va_list ap); +extern int vfprintf(FILE *stream, const char *format, va_list ap); + +#include "printf1.h" +#include "real_world.h" +#include "wide_string.h" +#include "format.h" +#include "pri_macros.h" diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/StackAddressEscapes/manager.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/StackAddressEscapes/manager.cpp index 843ffb340be..8b73bffb04a 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/StackAddressEscapes/manager.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/StackAddressEscapes/manager.cpp @@ -1,54 +1,54 @@ -// test cases for StackAddressEscapes.ql - -namespace std -{ - class string; - - template class vector - { - }; -}; - -class manager -{ -public: - manager() {}; - ~manager() {}; -}; - -class resource -{ -public: - resource(manager *_m) : m(_m) {}; - - void set_strings(std::vector const &_strings); - -private: - manager *m; - std::vector const *strings; -}; - -void resource :: set_strings(std::vector const &_strings) -{ - strings = &_strings; -} - -manager *glob_man; - -manager *test_managers() -{ - manager man; - manager *man_ptr; - man_ptr = &man; - - resource a(&man); // BAD: stack address `&man` escapes [NOT DETECTED] - resource b(man_ptr); // BAD: stack address `man_ptr` escapes [NOT DETECTED] - resource *c = new resource(&man); // BAD: stack address `&man` escapes [NOT DETECTED] - - std::vector vs; - a.set_strings(vs); // BAD: stack address `&vs` escapes [NOT DETECTED] - - glob_man = &man; // BAD: stack address `&man` escapes - - return &man; // BAD: stack address `&man` escapes [NOT DETECTED] -} +// test cases for StackAddressEscapes.ql + +namespace std +{ + class string; + + template class vector + { + }; +}; + +class manager +{ +public: + manager() {}; + ~manager() {}; +}; + +class resource +{ +public: + resource(manager *_m) : m(_m) {}; + + void set_strings(std::vector const &_strings); + +private: + manager *m; + std::vector const *strings; +}; + +void resource :: set_strings(std::vector const &_strings) +{ + strings = &_strings; +} + +manager *glob_man; + +manager *test_managers() +{ + manager man; + manager *man_ptr; + man_ptr = &man; + + resource a(&man); // BAD: stack address `&man` escapes [NOT DETECTED] + resource b(man_ptr); // BAD: stack address `man_ptr` escapes [NOT DETECTED] + resource *c = new resource(&man); // BAD: stack address `&man` escapes [NOT DETECTED] + + std::vector vs; + a.set_strings(vs); // BAD: stack address `&vs` escapes [NOT DETECTED] + + glob_man = &man; // BAD: stack address `&man` escapes + + return &man; // BAD: stack address `&man` escapes [NOT DETECTED] +} diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-253/HResultBooleanConversion.c b/cpp/ql/test/query-tests/Security/CWE/CWE-253/HResultBooleanConversion.c new file mode 100644 index 00000000000..9edcd34a8df --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-253/HResultBooleanConversion.c @@ -0,0 +1,100 @@ +// semmle-extractor-options: --microsoft +// winnt.h +typedef long HRESULT; +#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0) +#define FAILED(hr) (((HRESULT)(hr)) < 0) + +typedef _Bool bool; +#define FALSE 0 + +// minwindef.h +typedef int BOOL; +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +// winerror.h +#define S_OK ((HRESULT)0L) +#define S_FALSE ((HRESULT)1L) +#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc) +#define E_UNEXPECTED _HRESULT_TYPEDEF_(0x8000FFFFL) + +HRESULT HresultFunction() +{ + return S_OK; +} + +BOOL BoolFunction() +{ + return FALSE; +} + +bool BoolFunction2() +{ + return FALSE; +} + +HRESULT IncorrectHresultFunction() +{ + return BoolFunction(); // BUG +} + +HRESULT IncorrectHresultFunction2() +{ + return BoolFunction2(); // BUG +} + +void IncorrectTypeConversionTest() { + + HRESULT hr = HresultFunction(); + if ((BOOL)hr) // BUG + { + // ... + } + if ((bool)hr) // BUG + { + // ... + } + if (SUCCEEDED(hr)) // Correct Usage + { + // ... + } + + if (SUCCEEDED(BoolFunction())) // BUG + { + // ... + } + if (SUCCEEDED(BoolFunction2())) // BUG + { + // ... + } + if (BoolFunction()) // Correct Usage + { + // ... + } + BOOL b = IncorrectHresultFunction(); // BUG + bool b2 = IncorrectHresultFunction(); // BUG + + hr = E_UNEXPECTED; + if (!hr) // BUG + { + // ... + } + if (!FAILED(hr)) // Correct Usage + { + // ... + } + + hr = S_FALSE; + if (hr) // BUG + { + // ... + } + if (SUCCEEDED(hr)) // Correct Usage + { + // ... + } +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-253/HResultBooleanConversion.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-253/HResultBooleanConversion.cpp new file mode 100644 index 00000000000..04588c24264 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-253/HResultBooleanConversion.cpp @@ -0,0 +1,97 @@ +// semmle-extractor-options: --microsoft +// winnt.h +typedef long HRESULT; +#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0) +#define FAILED(hr) (((HRESULT)(hr)) < 0) + +// minwindef.h +typedef int BOOL; +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +// winerror.h +#define S_OK ((HRESULT)0L) +#define S_FALSE ((HRESULT)1L) +#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc) +#define E_UNEXPECTED _HRESULT_TYPEDEF_(0x8000FFFFL) + +HRESULT HresultFunction() +{ + return S_OK; +} + +BOOL BoolFunction() +{ + return FALSE; +} + +bool BoolFunction2() +{ + return FALSE; +} + +HRESULT IncorrectHresultFunction() +{ + return BoolFunction(); // BUG +} + +HRESULT IncorrectHresultFunction2() +{ + return BoolFunction2(); // BUG +} + +void IncorrectTypeConversionTest() { + + HRESULT hr = HresultFunction(); + if ((BOOL)hr) // BUG + { + // ... + } + if ((bool)hr) // BUG + { + // ... + } + if (SUCCEEDED(hr)) // Correct Usage + { + // ... + } + + if (SUCCEEDED(BoolFunction())) // BUG + { + // ... + } + if (SUCCEEDED(BoolFunction2())) // BUG + { + // ... + } + if (BoolFunction()) // Correct Usage + { + // ... + } + BOOL b = IncorrectHresultFunction(); // BUG + bool b2 = IncorrectHresultFunction(); // BUG + + hr = E_UNEXPECTED; + if (!hr) // BUG + { + // ... + } + if (!FAILED(hr)) // Correct Usage + { + // ... + } + + hr = S_FALSE; + if (hr) // BUG + { + // ... + } + if (SUCCEEDED(hr)) // Correct Usage + { + // ... + } +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-253/HResultBooleanConversion.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-253/HResultBooleanConversion.expected new file mode 100644 index 00000000000..15996702920 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-253/HResultBooleanConversion.expected @@ -0,0 +1,20 @@ +| HResultBooleanConversion.c:42:12:42:23 | call to BoolFunction | Implicit conversion from BOOL to HRESULT | +| HResultBooleanConversion.c:47:12:47:24 | call to BoolFunction2 | Implicit conversion from bool to HRESULT | +| HResultBooleanConversion.c:53:15:53:16 | hr | Explicit conversion from HRESULT to BOOL | +| HResultBooleanConversion.c:57:15:57:16 | hr | Explicit conversion from HRESULT to bool | +| HResultBooleanConversion.c:66:9:66:33 | (...) | Explicit conversion from BOOL to HRESULT | +| HResultBooleanConversion.c:70:9:70:34 | (...) | Explicit conversion from bool to HRESULT | +| HResultBooleanConversion.c:78:14:78:37 | call to IncorrectHresultFunction | Implicit conversion from HRESULT to BOOL | +| HResultBooleanConversion.c:79:15:79:38 | call to IncorrectHresultFunction | Implicit conversion from HRESULT to bool | +| HResultBooleanConversion.c:82:10:82:11 | hr | Usage of a type HRESULT as an argument of a unary logical operation | +| HResultBooleanConversion.c:92:9:92:10 | hr | Direct usage of a type HRESULT as a conditional expression | +| HResultBooleanConversion.cpp:39:12:39:23 | call to BoolFunction | Implicit conversion from BOOL to HRESULT | +| HResultBooleanConversion.cpp:44:12:44:24 | call to BoolFunction2 | Implicit conversion from bool to HRESULT | +| HResultBooleanConversion.cpp:50:15:50:16 | hr | Explicit conversion from HRESULT to BOOL | +| HResultBooleanConversion.cpp:54:15:54:16 | hr | Explicit conversion from HRESULT to bool | +| HResultBooleanConversion.cpp:63:9:63:33 | (...) | Explicit conversion from BOOL to HRESULT | +| HResultBooleanConversion.cpp:67:9:67:34 | (...) | Explicit conversion from bool to HRESULT | +| HResultBooleanConversion.cpp:75:14:75:37 | call to IncorrectHresultFunction | Implicit conversion from HRESULT to BOOL | +| HResultBooleanConversion.cpp:76:15:76:38 | call to IncorrectHresultFunction | Implicit conversion from HRESULT to bool | +| HResultBooleanConversion.cpp:79:10:79:11 | hr | Implicit conversion from HRESULT to bool | +| HResultBooleanConversion.cpp:89:9:89:10 | hr | Implicit conversion from HRESULT to bool | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-253/HResultBooleanConversion.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-253/HResultBooleanConversion.qlref new file mode 100644 index 00000000000..a345e5c6dfb --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-253/HResultBooleanConversion.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-253/HResultBooleanConversion.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/jsf/4.09 Style/AV Rule 53 54/test.CPP b/cpp/ql/test/query-tests/jsf/4.09 Style/AV Rule 53 54/test.CPP index c17c5ea6e5f..04637aa9c90 100644 --- a/cpp/ql/test/query-tests/jsf/4.09 Style/AV Rule 53 54/test.CPP +++ b/cpp/ql/test/query-tests/jsf/4.09 Style/AV Rule 53 54/test.CPP @@ -1,2 +1,2 @@ -#include "test.c++" -#include "test.hpp" +#include "test.c++" +#include "test.hpp" diff --git a/cpp/ql/test/query-tests/jsf/4.09 Style/AV Rule 53 54/test.c b/cpp/ql/test/query-tests/jsf/4.09 Style/AV Rule 53 54/test.c index 1da91c1cfda..47c2408c2fb 100644 --- a/cpp/ql/test/query-tests/jsf/4.09 Style/AV Rule 53 54/test.c +++ b/cpp/ql/test/query-tests/jsf/4.09 Style/AV Rule 53 54/test.c @@ -1,4 +1,4 @@ -#include "test" -#include "test.abc" -#include "test.H" -#include "test'.h" +#include "test" +#include "test.abc" +#include "test.H" +#include "test'.h" diff --git a/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 73/original.cpp b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 73/original.cpp index 78001340db4..5c86702e2c2 100644 --- a/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 73/original.cpp +++ b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 73/original.cpp @@ -1,160 +1,160 @@ -// bad: gratuitous default constructor -class Bad -{ -private: - int key; - int value; -public: - Bad(); - Bad(int); - Bad(int, int); - int cmp(const Bad& that); -}; - -Bad::Bad() : key(-1) // non-compliant -{ -} - -Bad::Bad(int k) : key(k) // compliant -{ -} - -Bad::Bad(int k, int v) // compliant -{ - key = k; - value = v; -} - -int Bad::cmp(const Bad& that) -{ - if(this->key == -1) - return 1; - if(that.key == -1) - return -1; - return this->key - that.key; -} - -// good: default constructor is necessary because we allocate an array of Good -class Good -{ -private: - char *cp; -public: - Good(); - Good(char *const cpp); - char getChar(); -}; - -Good::Good() : cp(0) // compliant -{ -} - -Good::Good(char *const cpp) : cp(cpp) -{ -} - -char Good::getChar() -{ - if(cp == 0) - return '\0'; - return *cp; -} - -Good *gd = new Good[16]; - -// good: default constructor is necessary because we instantiate a template with AlsoGood -class AlsoGood -{ -private: - char *cp; -public: - AlsoGood(); - AlsoGood(char *const cpp); - char getChar(); -}; - -AlsoGood::AlsoGood() // compliant [FALSE POSITIVE] -{ - cp = 0; -} - -AlsoGood::AlsoGood(char *const cpp) : cp(cpp) -{ -} - -char AlsoGood::getChar() -{ - if(cp == 0) - return '\0'; - return *cp; -} - -template class Container { -private: - T *data; -public: - Container(); -}; - -template Container::Container() -{ - data = new T(); -} - -Container *foo; - -// good: default constructor is convenient since StillGood is a virtual base class -class StillGood -{ -private: - char *cp; -public: - StillGood(); - StillGood(char *const cpp); - char getChar(); -}; - -StillGood::StillGood() : cp(0) // compliant -{ -} - -StillGood::StillGood(char *const cpp) : cp(cpp) -{ -} - -char StillGood::getChar() -{ - if(cp == 0) - return '\0'; - return *cp; -} - -class Child : public virtual StillGood -{ -}; - -double sqrt(double d); - -// good: members have sensible default values -class Coord -{ -private: - double x, y; -public: - Coord(); - Coord(double, double); - double dist(); -}; - -Coord::Coord() : x(0), y(0) // compliant -{ -} - -Coord::Coord(double x, double y) : x(x), y(y) -{ -} - -double Coord::dist() -{ - return sqrt(x*x+y*y); -} +// bad: gratuitous default constructor +class Bad +{ +private: + int key; + int value; +public: + Bad(); + Bad(int); + Bad(int, int); + int cmp(const Bad& that); +}; + +Bad::Bad() : key(-1) // non-compliant +{ +} + +Bad::Bad(int k) : key(k) // compliant +{ +} + +Bad::Bad(int k, int v) // compliant +{ + key = k; + value = v; +} + +int Bad::cmp(const Bad& that) +{ + if(this->key == -1) + return 1; + if(that.key == -1) + return -1; + return this->key - that.key; +} + +// good: default constructor is necessary because we allocate an array of Good +class Good +{ +private: + char *cp; +public: + Good(); + Good(char *const cpp); + char getChar(); +}; + +Good::Good() : cp(0) // compliant +{ +} + +Good::Good(char *const cpp) : cp(cpp) +{ +} + +char Good::getChar() +{ + if(cp == 0) + return '\0'; + return *cp; +} + +Good *gd = new Good[16]; + +// good: default constructor is necessary because we instantiate a template with AlsoGood +class AlsoGood +{ +private: + char *cp; +public: + AlsoGood(); + AlsoGood(char *const cpp); + char getChar(); +}; + +AlsoGood::AlsoGood() // compliant [FALSE POSITIVE] +{ + cp = 0; +} + +AlsoGood::AlsoGood(char *const cpp) : cp(cpp) +{ +} + +char AlsoGood::getChar() +{ + if(cp == 0) + return '\0'; + return *cp; +} + +template class Container { +private: + T *data; +public: + Container(); +}; + +template Container::Container() +{ + data = new T(); +} + +Container *foo; + +// good: default constructor is convenient since StillGood is a virtual base class +class StillGood +{ +private: + char *cp; +public: + StillGood(); + StillGood(char *const cpp); + char getChar(); +}; + +StillGood::StillGood() : cp(0) // compliant +{ +} + +StillGood::StillGood(char *const cpp) : cp(cpp) +{ +} + +char StillGood::getChar() +{ + if(cp == 0) + return '\0'; + return *cp; +} + +class Child : public virtual StillGood +{ +}; + +double sqrt(double d); + +// good: members have sensible default values +class Coord +{ +private: + double x, y; +public: + Coord(); + Coord(double, double); + double dist(); +}; + +Coord::Coord() : x(0), y(0) // compliant +{ +} + +Coord::Coord(double x, double y) : x(x), y(y) +{ +} + +double Coord::dist() +{ + return sqrt(x*x+y*y); +} diff --git a/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 78/AV Rule 78.cpp b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 78/AV Rule 78.cpp index 08442008309..7612ac07c8c 100644 --- a/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 78/AV Rule 78.cpp +++ b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 78/AV Rule 78.cpp @@ -1,108 +1,108 @@ -struct HasDtor -{ - ~HasDtor(); -}; - -struct Base_NonVirtual_NoDtor -{ - void NonVirtualFunction(); -}; - -struct Base_NonVirtual_VirtualDtor -{ - virtual ~Base_NonVirtual_VirtualDtor(); - void NonVirtualFunction(); -}; - -struct Base_NonVirtual_NonVirtualDtor -{ - ~Base_NonVirtual_NonVirtualDtor(); - void NonVirtualFunction(); -}; - -struct Base_NonVirtual_ImplicitDtor -{ - HasDtor m_hasDtor; - void NonVirtualFunction(); -}; - -struct Derived_NonVirtual_NoDtor : public Base_NonVirtual_NoDtor -{ -}; - -struct Derived_NonVirtual_VirtualDtor : public Base_NonVirtual_VirtualDtor -{ -}; - -struct Derived_NonVirtual_NonVirtualDtor : public Base_NonVirtual_NonVirtualDtor -{ -}; - -struct Derived_NonVirtual_ImplicitDtor : public Base_NonVirtual_ImplicitDtor -{ -}; - -struct Base_Virtual_NoDtor -{ - virtual void VirtualFunction(); -}; - -struct Base_Virtual_VirtualDtor -{ - virtual ~Base_Virtual_VirtualDtor(); - virtual void VirtualFunction(); -}; - -struct Base_Virtual_NonVirtualDtor -{ - ~Base_Virtual_NonVirtualDtor(); - virtual void VirtualFunction(); -}; - -struct Base_Virtual_ImplicitDtor -{ - HasDtor m_hasDtor; - virtual void VirtualFunction(); -}; - -struct Base_Virtual_NonVirtualDtorWithDefinition -{ - ~Base_Virtual_NonVirtualDtorWithDefinition(); - virtual void VirtualFunction(); -}; - -Base_Virtual_NonVirtualDtorWithDefinition::~Base_Virtual_NonVirtualDtorWithDefinition() -{ -} - -struct Base_Virtual_NonVirtualDtorWithInlineDefinition -{ - ~Base_Virtual_NonVirtualDtorWithInlineDefinition() - { - } - virtual void VirtualFunction(); -}; - -struct Derived_Virtual_NoDtor : public Base_Virtual_NoDtor -{ -}; - -struct Derived_Virtual_VirtualDtor : public Base_Virtual_VirtualDtor -{ -}; - -struct Derived_Virtual_NonVirtualDtor : public Base_Virtual_NonVirtualDtor -{ -}; - -struct Derived_Virtual_ImplicitDtor : public Base_Virtual_ImplicitDtor -{ -}; - -struct Derived_Virtual_NonVirtualDtorWithDefinition: public Base_Virtual_NonVirtualDtorWithDefinition -{ -}; - -struct Derived_Virtual_NonVirtualDtorWithInlineDefinition: public Base_Virtual_NonVirtualDtorWithInlineDefinition -{ -}; +struct HasDtor +{ + ~HasDtor(); +}; + +struct Base_NonVirtual_NoDtor +{ + void NonVirtualFunction(); +}; + +struct Base_NonVirtual_VirtualDtor +{ + virtual ~Base_NonVirtual_VirtualDtor(); + void NonVirtualFunction(); +}; + +struct Base_NonVirtual_NonVirtualDtor +{ + ~Base_NonVirtual_NonVirtualDtor(); + void NonVirtualFunction(); +}; + +struct Base_NonVirtual_ImplicitDtor +{ + HasDtor m_hasDtor; + void NonVirtualFunction(); +}; + +struct Derived_NonVirtual_NoDtor : public Base_NonVirtual_NoDtor +{ +}; + +struct Derived_NonVirtual_VirtualDtor : public Base_NonVirtual_VirtualDtor +{ +}; + +struct Derived_NonVirtual_NonVirtualDtor : public Base_NonVirtual_NonVirtualDtor +{ +}; + +struct Derived_NonVirtual_ImplicitDtor : public Base_NonVirtual_ImplicitDtor +{ +}; + +struct Base_Virtual_NoDtor +{ + virtual void VirtualFunction(); +}; + +struct Base_Virtual_VirtualDtor +{ + virtual ~Base_Virtual_VirtualDtor(); + virtual void VirtualFunction(); +}; + +struct Base_Virtual_NonVirtualDtor +{ + ~Base_Virtual_NonVirtualDtor(); + virtual void VirtualFunction(); +}; + +struct Base_Virtual_ImplicitDtor +{ + HasDtor m_hasDtor; + virtual void VirtualFunction(); +}; + +struct Base_Virtual_NonVirtualDtorWithDefinition +{ + ~Base_Virtual_NonVirtualDtorWithDefinition(); + virtual void VirtualFunction(); +}; + +Base_Virtual_NonVirtualDtorWithDefinition::~Base_Virtual_NonVirtualDtorWithDefinition() +{ +} + +struct Base_Virtual_NonVirtualDtorWithInlineDefinition +{ + ~Base_Virtual_NonVirtualDtorWithInlineDefinition() + { + } + virtual void VirtualFunction(); +}; + +struct Derived_Virtual_NoDtor : public Base_Virtual_NoDtor +{ +}; + +struct Derived_Virtual_VirtualDtor : public Base_Virtual_VirtualDtor +{ +}; + +struct Derived_Virtual_NonVirtualDtor : public Base_Virtual_NonVirtualDtor +{ +}; + +struct Derived_Virtual_ImplicitDtor : public Base_Virtual_ImplicitDtor +{ +}; + +struct Derived_Virtual_NonVirtualDtorWithDefinition: public Base_Virtual_NonVirtualDtorWithDefinition +{ +}; + +struct Derived_Virtual_NonVirtualDtorWithInlineDefinition: public Base_Virtual_NonVirtualDtorWithInlineDefinition +{ +}; diff --git a/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/AV Rule 79.expected b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/AV Rule 79.expected index 85f71ce6446..eed2f14a99f 100644 --- a/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/AV Rule 79.expected +++ b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/AV Rule 79.expected @@ -11,5 +11,9 @@ | ExternalOwners.cpp:49:3:49:20 | ... = ... | Resource a is acquired by class MyScreen but not released anywhere in this class. | | ListDelete.cpp:21:3:21:21 | ... = ... | Resource first is acquired by class MyThingColection but not released anywhere in this class. | | NoDestructor.cpp:23:3:23:20 | ... = ... | Resource n is acquired by class MyClass5 but not released anywhere in this class. | +| PlacementNew.cpp:36:3:36:36 | ... = ... | Resource p1 is acquired by class MyTestForPlacementNew but not released anywhere in this class. | | SelfRegistering.cpp:25:3:25:24 | ... = ... | Resource side is acquired by class MyOwner but not released anywhere in this class. | -| Variants.cpp:23:3:23:13 | ... = ... | Resource f is acquired by class MyClass4 but not released anywhere in this class. | +| Variants.cpp:25:3:25:13 | ... = ... | Resource f is acquired by class MyClass4 but not released anywhere in this class. | +| Variants.cpp:65:3:65:17 | ... = ... | Resource a is acquired by class MyClass6 but not released anywhere in this class. | +| Variants.cpp:66:3:66:36 | ... = ... | Resource b is acquired by class MyClass6 but not released anywhere in this class. | +| Variants.cpp:67:3:67:41 | ... = ... | Resource c is acquired by class MyClass6 but not released anywhere in this class. | diff --git a/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/PlacementNew.cpp b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/PlacementNew.cpp new file mode 100644 index 00000000000..c7794857cb9 --- /dev/null +++ b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/PlacementNew.cpp @@ -0,0 +1,47 @@ + +typedef unsigned long size_t; + +namespace std +{ + using ::size_t; + struct nothrow_t {}; + extern const nothrow_t nothrow; +} + +// nothrow new +void* operator new(std::size_t size, const std::nothrow_t&) throw(); + +// placement new +void* operator new (std::size_t size, void* ptr) throw(); + +// --- + +class MyClassForPlacementNew +{ +public: + MyClassForPlacementNew(int _v) : v(_v) {} + ~MyClassForPlacementNew() {} + +private: + int v; +}; + +class MyTestForPlacementNew +{ +public: + MyTestForPlacementNew() + { + void *buffer_ptr = buffer; + + p1 = new MyClassForPlacementNew(1); // BAD: not released + p2 = new (std::nothrow) MyClassForPlacementNew(2); // BAD: not released [NOT DETECTED] + p3 = new (buffer_ptr) MyClassForPlacementNew(3); // GOOD: placement new, not an allocation + } + + ~MyTestForPlacementNew() + { + } + + MyClassForPlacementNew *p1, *p2, *p3; + char buffer[sizeof(MyClassForPlacementNew)]; +}; diff --git a/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/Variants.cpp b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/Variants.cpp index bbbfab1fc92..dbeee230de4 100644 --- a/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/Variants.cpp +++ b/cpp/ql/test/query-tests/jsf/4.10 Classes/AV Rule 79/Variants.cpp @@ -2,6 +2,8 @@ // library typedef unsigned int size_t; void *malloc(size_t size); +void *calloc(size_t nmemb, size_t size); +void *realloc(void *ptr, size_t size); void free(void* ptr); int *ID(int *x) @@ -34,3 +36,40 @@ public: int *a, *b, *c, *d, *e, *f, *g; }; + +class MyClass5 +{ +public: + MyClass5() + { + a = new int[10]; // GOOD + b = (int *)calloc(10, sizeof(int)); // GOOD + c = (int *)realloc(0, 10 * sizeof(int)); // GOOD + } + + ~MyClass5() + { + delete [] a; + free(b); + free(c); + } + + int *a, *b, *c; +}; + +class MyClass6 +{ +public: + MyClass6() + { + a = new int[10]; // BAD + b = (int *)calloc(10, sizeof(int)); // BAD + c = (int *)realloc(0, 10 * sizeof(int)); // BAD + } + + ~MyClass6() + { + } + + int *a, *b, *c; +}; diff --git a/cpp/ql/test/successor-tests/assignexpr/assignexpr.cpp b/cpp/ql/test/successor-tests/assignexpr/assignexpr.cpp index 1bd6c572eec..b1ceec88282 100644 --- a/cpp/ql/test/successor-tests/assignexpr/assignexpr.cpp +++ b/cpp/ql/test/successor-tests/assignexpr/assignexpr.cpp @@ -1,11 +1,11 @@ -class C { - public: - int i; -}; - -void f() { - C c; - int a, b; - c.i = a + b; - ; -} +class C { + public: + int i; +}; + +void f() { + C c; + int a, b; + c.i = a + b; + ; +} diff --git a/cpp/ql/test/successor-tests/block/dummyblock/dummyblock.c b/cpp/ql/test/successor-tests/block/dummyblock/dummyblock.c index f113a35f204..1307903ecf5 100644 --- a/cpp/ql/test/successor-tests/block/dummyblock/dummyblock.c +++ b/cpp/ql/test/successor-tests/block/dummyblock/dummyblock.c @@ -1,4 +1,4 @@ -void f() { - if (1) - ; -} +void f() { + if (1) + ; +} diff --git a/cpp/ql/test/successor-tests/block/emptyblock/emptyblock.c b/cpp/ql/test/successor-tests/block/emptyblock/emptyblock.c index 87680af388d..33ef4b879cd 100644 --- a/cpp/ql/test/successor-tests/block/emptyblock/emptyblock.c +++ b/cpp/ql/test/successor-tests/block/emptyblock/emptyblock.c @@ -1,5 +1,5 @@ -void f() { - { - } - ; -} +void f() { + { + } + ; +} diff --git a/cpp/ql/test/successor-tests/callexpr/args/membercallexpr/membercallexpr.cpp b/cpp/ql/test/successor-tests/callexpr/args/membercallexpr/membercallexpr.cpp index 9d4edb8979b..5009f913255 100644 --- a/cpp/ql/test/successor-tests/callexpr/args/membercallexpr/membercallexpr.cpp +++ b/cpp/ql/test/successor-tests/callexpr/args/membercallexpr/membercallexpr.cpp @@ -1,11 +1,11 @@ -class C { - public: - C* d; - void g(int x, int y); -}; - -void f() { - int i, j, k, l; - C *c; - c->d->g(i + j, k - l); -} +class C { + public: + C* d; + void g(int x, int y); +}; + +void f() { + int i, j, k, l; + C *c; + c->d->g(i + j, k - l); +} diff --git a/cpp/ql/test/successor-tests/callexpr/args/staticmembercallexpr/staticmembercallexpr.cpp b/cpp/ql/test/successor-tests/callexpr/args/staticmembercallexpr/staticmembercallexpr.cpp index 10acb0fbc1f..df553720dab 100644 --- a/cpp/ql/test/successor-tests/callexpr/args/staticmembercallexpr/staticmembercallexpr.cpp +++ b/cpp/ql/test/successor-tests/callexpr/args/staticmembercallexpr/staticmembercallexpr.cpp @@ -1,11 +1,11 @@ -class C { - public: - C* d; - static void g(int x, int y); -}; - -void f() { - int i, j, k, l; - C c; - c.d->g(i + j, k - l); -} +class C { + public: + C* d; + static void g(int x, int y); +}; + +void f() { + int i, j, k, l; + C c; + c.d->g(i + j, k - l); +} diff --git a/cpp/ql/test/successor-tests/callexpr/noargs/membercallexpr/membercallexpr.cpp b/cpp/ql/test/successor-tests/callexpr/noargs/membercallexpr/membercallexpr.cpp index 1548f3f81a7..035db2d5856 100644 --- a/cpp/ql/test/successor-tests/callexpr/noargs/membercallexpr/membercallexpr.cpp +++ b/cpp/ql/test/successor-tests/callexpr/noargs/membercallexpr/membercallexpr.cpp @@ -1,10 +1,10 @@ -class C { - public: - void g(); -}; - -void f() { - C *c; - c->g(); - ; -} +class C { + public: + void g(); +}; + +void f() { + C *c; + c->g(); + ; +} diff --git a/cpp/ql/test/successor-tests/callexpr/noargs/nonmembercallexpr/nonmembercallexpr.c b/cpp/ql/test/successor-tests/callexpr/noargs/nonmembercallexpr/nonmembercallexpr.c index fc37abcdfdb..4c949924900 100644 --- a/cpp/ql/test/successor-tests/callexpr/noargs/nonmembercallexpr/nonmembercallexpr.c +++ b/cpp/ql/test/successor-tests/callexpr/noargs/nonmembercallexpr/nonmembercallexpr.c @@ -1,6 +1,6 @@ -void g() { } - -void f() { - g(); - ; -} +void g() { } + +void f() { + g(); + ; +} diff --git a/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfp2callexpr/nonmemberfp2callexpr.c b/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfp2callexpr/nonmemberfp2callexpr.c index b04b51fcb14..9e458f2f50d 100644 --- a/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfp2callexpr/nonmemberfp2callexpr.c +++ b/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfp2callexpr/nonmemberfp2callexpr.c @@ -1,6 +1,6 @@ -void (*g())(); - -void f() { - g()(); - ; -} +void (*g())(); + +void f() { + g()(); + ; +} diff --git a/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfpcallexpr/nonmemberfpcallexpr.c b/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfpcallexpr/nonmemberfpcallexpr.c index e22a8d4a1a0..51e06cec04b 100644 --- a/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfpcallexpr/nonmemberfpcallexpr.c +++ b/cpp/ql/test/successor-tests/callexpr/noargs/nonmemberfpcallexpr/nonmemberfpcallexpr.c @@ -1,5 +1,5 @@ -void f() { - int (*g)(); - g(); - ; -} +void f() { + int (*g)(); + g(); + ; +} diff --git a/cpp/ql/test/successor-tests/callexpr/noargs/pmcallexpr/pmcallexpr.cpp b/cpp/ql/test/successor-tests/callexpr/noargs/pmcallexpr/pmcallexpr.cpp index 76c085f8ec0..75e143d846a 100644 --- a/cpp/ql/test/successor-tests/callexpr/noargs/pmcallexpr/pmcallexpr.cpp +++ b/cpp/ql/test/successor-tests/callexpr/noargs/pmcallexpr/pmcallexpr.cpp @@ -1,10 +1,10 @@ -class C { - public: - void (C::*g)(); -}; - -void f() { - C *c, *d; - (c->*(d->g))(); - ; -} +class C { + public: + void (C::*g)(); +}; + +void f() { + C *c, *d; + (c->*(d->g))(); + ; +} diff --git a/cpp/ql/test/successor-tests/callexpr/noargs/staticmembercallexpr/staticmembercallexpr.cpp b/cpp/ql/test/successor-tests/callexpr/noargs/staticmembercallexpr/staticmembercallexpr.cpp index 0b744c9d1c1..216b450e0dd 100644 --- a/cpp/ql/test/successor-tests/callexpr/noargs/staticmembercallexpr/staticmembercallexpr.cpp +++ b/cpp/ql/test/successor-tests/callexpr/noargs/staticmembercallexpr/staticmembercallexpr.cpp @@ -1,10 +1,10 @@ -class C { - public: - static void g(); -}; - -void f() { - C c; - c.g(); - ; -} +class C { + public: + static void g(); +}; + +void f() { + C c; + c.g(); + ; +} diff --git a/cpp/ql/test/successor-tests/deleteexpr/defdestructordeleteexpr/defdestructordeleteexpr.cpp b/cpp/ql/test/successor-tests/deleteexpr/defdestructordeleteexpr/defdestructordeleteexpr.cpp index ce92915640f..213898543a6 100644 --- a/cpp/ql/test/successor-tests/deleteexpr/defdestructordeleteexpr/defdestructordeleteexpr.cpp +++ b/cpp/ql/test/successor-tests/deleteexpr/defdestructordeleteexpr/defdestructordeleteexpr.cpp @@ -1,6 +1,6 @@ -class C { }; - -void f() { - C* c = new C(); - delete c; -} +class C { }; + +void f() { + C* c = new C(); + delete c; +} diff --git a/cpp/ql/test/successor-tests/deleteexpr/deleteexpr/deleteexpr.cpp b/cpp/ql/test/successor-tests/deleteexpr/deleteexpr/deleteexpr.cpp index 1b22a4736b1..5e997100e37 100644 --- a/cpp/ql/test/successor-tests/deleteexpr/deleteexpr/deleteexpr.cpp +++ b/cpp/ql/test/successor-tests/deleteexpr/deleteexpr/deleteexpr.cpp @@ -1,9 +1,9 @@ -class C { - public: - ~C(); -}; - -void f() { - C* c = new C(); - delete c; -} +class C { + public: + ~C(); +}; + +void f() { + C* c = new C(); + delete c; +} diff --git a/cpp/ql/test/successor-tests/dostmt/dostmt.c b/cpp/ql/test/successor-tests/dostmt/dostmt.c index 1b8f4ed2e69..5f1d14488dd 100644 --- a/cpp/ql/test/successor-tests/dostmt/dostmt.c +++ b/cpp/ql/test/successor-tests/dostmt/dostmt.c @@ -1,38 +1,38 @@ -void always_false() { - do { - l1:; - } while(0); - l2:; -} - -void always_true_1() { - do { - l1:; - break; - } while(1); - l2:; -} - -void always_true_2() { - do { - l1:; - break; - l2:; - } while(1); - l3:; -} - -void always_true_3() { - do { - l1:; - } while(1); - l2:; -} - -void normal() { - int i = 0; - do { - ++i; - } while(i < 10); - l:; -} +void always_false() { + do { + l1:; + } while(0); + l2:; +} + +void always_true_1() { + do { + l1:; + break; + } while(1); + l2:; +} + +void always_true_2() { + do { + l1:; + break; + l2:; + } while(1); + l3:; +} + +void always_true_3() { + do { + l1:; + } while(1); + l2:; +} + +void normal() { + int i = 0; + do { + ++i; + } while(i < 10); + l:; +} diff --git a/cpp/ql/test/successor-tests/enum/enum.c b/cpp/ql/test/successor-tests/enum/enum.c index dd5be9ec595..4e714c7c940 100644 --- a/cpp/ql/test/successor-tests/enum/enum.c +++ b/cpp/ql/test/successor-tests/enum/enum.c @@ -1,7 +1,7 @@ -enum { - a = 1 + 1 -}; - -int f() { - return a; -} +enum { + a = 1 + 1 +}; + +int f() { + return a; +} diff --git a/cpp/ql/test/successor-tests/exceptionhandler/ellipsisexceptionhandler/ellipsisexceptionhandler.cpp b/cpp/ql/test/successor-tests/exceptionhandler/ellipsisexceptionhandler/ellipsisexceptionhandler.cpp index 8c6f2a7cb39..97666c3bf85 100644 --- a/cpp/ql/test/successor-tests/exceptionhandler/ellipsisexceptionhandler/ellipsisexceptionhandler.cpp +++ b/cpp/ql/test/successor-tests/exceptionhandler/ellipsisexceptionhandler/ellipsisexceptionhandler.cpp @@ -1,17 +1,17 @@ -void f() { - try { - try { - throw 1; - } catch (int i) { - } catch (...) { - } - } catch (int j) { - } -} - -void g(bool condition) { - try { - if (condition) throw 1; - } catch (...) { - } -} +void f() { + try { + try { + throw 1; + } catch (int i) { + } catch (...) { + } + } catch (int j) { + } +} + +void g(bool condition) { + try { + if (condition) throw 1; + } catch (...) { + } +} diff --git a/cpp/ql/test/successor-tests/exceptionhandler/exceptionhandler/exceptionhandler.cpp b/cpp/ql/test/successor-tests/exceptionhandler/exceptionhandler/exceptionhandler.cpp index e5818c89125..66c20661fd1 100644 --- a/cpp/ql/test/successor-tests/exceptionhandler/exceptionhandler/exceptionhandler.cpp +++ b/cpp/ql/test/successor-tests/exceptionhandler/exceptionhandler/exceptionhandler.cpp @@ -1,22 +1,22 @@ -class C { }; -class D { }; - -void g() { - throw 1; -} - -void f() { - try { - try { - g(); - throw 2; -l: - } catch (int) { - 4; - } - } catch (C) { - 5; - } catch (D) { - 6; - } -} +class C { }; +class D { }; + +void g() { + throw 1; +} + +void f() { + try { + try { + g(); + throw 2; +l: + } catch (int) { + 4; + } + } catch (C) { + 5; + } catch (D) { + 6; + } +} diff --git a/cpp/ql/test/successor-tests/exprstmt/exprstmt.c b/cpp/ql/test/successor-tests/exprstmt/exprstmt.c index 745dee0c47d..a0ce2659424 100644 --- a/cpp/ql/test/successor-tests/exprstmt/exprstmt.c +++ b/cpp/ql/test/successor-tests/exprstmt/exprstmt.c @@ -1,4 +1,4 @@ -void f() { - 1; - ; -} +void f() { + 1; + ; +} diff --git a/cpp/ql/test/successor-tests/fieldaccessexpr/constmemberaccess/constmemberaccess.cpp b/cpp/ql/test/successor-tests/fieldaccessexpr/constmemberaccess/constmemberaccess.cpp index 74445da5a99..9a75ab5b2e9 100644 --- a/cpp/ql/test/successor-tests/fieldaccessexpr/constmemberaccess/constmemberaccess.cpp +++ b/cpp/ql/test/successor-tests/fieldaccessexpr/constmemberaccess/constmemberaccess.cpp @@ -1,10 +1,10 @@ -class C { - public: - int x; -}; - -void f() { - C *c; - int i; - i = c->x; +class C { + public: + int x; +}; + +void f() { + C *c; + int i; + i = c->x; } \ No newline at end of file diff --git a/cpp/ql/test/successor-tests/fieldaccessexpr/fieldaccess/fieldaccess.cpp b/cpp/ql/test/successor-tests/fieldaccessexpr/fieldaccess/fieldaccess.cpp index 74445da5a99..9a75ab5b2e9 100644 --- a/cpp/ql/test/successor-tests/fieldaccessexpr/fieldaccess/fieldaccess.cpp +++ b/cpp/ql/test/successor-tests/fieldaccessexpr/fieldaccess/fieldaccess.cpp @@ -1,10 +1,10 @@ -class C { - public: - int x; -}; - -void f() { - C *c; - int i; - i = c->x; +class C { + public: + int x; +}; + +void f() { + C *c; + int i; + i = c->x; } \ No newline at end of file diff --git a/cpp/ql/test/successor-tests/forstmt/forstmt/forstmt.cpp b/cpp/ql/test/successor-tests/forstmt/forstmt/forstmt.cpp index 2ccbd6b3f54..917ccb0bbfd 100644 --- a/cpp/ql/test/successor-tests/forstmt/forstmt/forstmt.cpp +++ b/cpp/ql/test/successor-tests/forstmt/forstmt/forstmt.cpp @@ -1,21 +1,21 @@ -void f1() { - for (int i = 0; i < 10; i++) { - l1: - } - ; -} - -void f2() { - for (int i = 0; false; i++) { // true edge pruned - } -} - -void f3() { - for (int i = 0; true; i++) { // false edge pruned - } -} - -void f4() { - for (int i = 0; i < 0; i++) { // true edge pruned - } +void f1() { + for (int i = 0; i < 10; i++) { + l1: + } + ; +} + +void f2() { + for (int i = 0; false; i++) { // true edge pruned + } +} + +void f3() { + for (int i = 0; true; i++) { // false edge pruned + } +} + +void f4() { + for (int i = 0; i < 0; i++) { // true edge pruned + } } \ No newline at end of file diff --git a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt.cpp b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt.cpp index e5257a9db53..d0587d8e85b 100644 --- a/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt.cpp +++ b/cpp/ql/test/successor-tests/forstmt/shortforstmt/shortforstmt.cpp @@ -1,38 +1,38 @@ -void always_false() { - for(;0;) { - l1:; - } - l2:; -} - -void always_true_1() { - for(;1;) { - l1:; - break; - } - l2:; -} - -void always_true_2() { - for(;1;) { - l1:; - if(0) break; - if(1) break; - l2:; - } - l3:; -} - -void always_true_3() { - for(;1;) { - l1:; - } - l2:; -} - -void normal(int x, int y) { - for(;x < y;) { - x = y; - } - l:; -} +void always_false() { + for(;0;) { + l1:; + } + l2:; +} + +void always_true_1() { + for(;1;) { + l1:; + break; + } + l2:; +} + +void always_true_2() { + for(;1;) { + l1:; + if(0) break; + if(1) break; + l2:; + } + l3:; +} + +void always_true_3() { + for(;1;) { + l1:; + } + l2:; +} + +void normal(int x, int y) { + for(;x < y;) { + x = y; + } + l:; +} diff --git a/cpp/ql/test/successor-tests/forstmt/tinyforstmt/tinyforstmt.c b/cpp/ql/test/successor-tests/forstmt/tinyforstmt/tinyforstmt.c index 129e2b279b5..cbb6465ab7b 100644 --- a/cpp/ql/test/successor-tests/forstmt/tinyforstmt/tinyforstmt.c +++ b/cpp/ql/test/successor-tests/forstmt/tinyforstmt/tinyforstmt.c @@ -1,5 +1,5 @@ -void f() { - for (;;) { - ; - } -} +void f() { + for (;;) { + ; + } +} diff --git a/cpp/ql/test/successor-tests/gotostmt/gotostmt.c b/cpp/ql/test/successor-tests/gotostmt/gotostmt.c index 318e26caf69..4a5e44f4b00 100644 --- a/cpp/ql/test/successor-tests/gotostmt/gotostmt.c +++ b/cpp/ql/test/successor-tests/gotostmt/gotostmt.c @@ -1,5 +1,5 @@ -void v() { - goto label; - ; -label: -} +void v() { + goto label; + ; +label: +} diff --git a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt.c b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt.c index 618b67dc789..c21e213c8c7 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt.c +++ b/cpp/ql/test/successor-tests/ifstmt/ifelsestmt/ifelsestmt.c @@ -1,45 +1,45 @@ -void always_false_1() { - if(0) { - l1:; - } - else { - l2:; - } - l3:; -} - -void always_false_2() { - if(0) - l1:; - else - l2:; - l3:; -} - -void always_true_1() { - if(1) { - l1:; - } - else { - l2:; - } - l3:; -} - -void always_true_2() { - if(1) - l1:; - else - l2:; - l3:; -} - -void normal(int x, int y) { - if(x == y) { - l1:; - } - else { - l2:; - } - l3:; -} +void always_false_1() { + if(0) { + l1:; + } + else { + l2:; + } + l3:; +} + +void always_false_2() { + if(0) + l1:; + else + l2:; + l3:; +} + +void always_true_1() { + if(1) { + l1:; + } + else { + l2:; + } + l3:; +} + +void always_true_2() { + if(1) + l1:; + else + l2:; + l3:; +} + +void normal(int x, int y) { + if(x == y) { + l1:; + } + else { + l2:; + } + l3:; +} diff --git a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt.c b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt.c index a98a1bfffe7..cf8c969277d 100644 --- a/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt.c +++ b/cpp/ql/test/successor-tests/ifstmt/ifstmt/ifstmt.c @@ -1,32 +1,32 @@ -void always_false_1() { - if(0) { - l1:; - } - l2:; -} - -void always_false_2() { - if(0) - l1:; - l2:; -} - -void always_true_1() { - if(1) { - l1:; - } - l2:; -} - -void always_true_2() { - if(1) - l1:; - l2:; -} - -void normal(int x, int y) { - if(x == y) { - l1:; - } - l2:; -} +void always_false_1() { + if(0) { + l1:; + } + l2:; +} + +void always_false_2() { + if(0) + l1:; + l2:; +} + +void always_true_1() { + if(1) { + l1:; + } + l2:; +} + +void always_true_2() { + if(1) + l1:; + l2:; +} + +void normal(int x, int y) { + if(x == y) { + l1:; + } + l2:; +} diff --git a/cpp/ql/test/successor-tests/initializer/aggregateinitializer/aggregateinitializer.c b/cpp/ql/test/successor-tests/initializer/aggregateinitializer/aggregateinitializer.c index 2c665328a18..463bd49e0a0 100644 --- a/cpp/ql/test/successor-tests/initializer/aggregateinitializer/aggregateinitializer.c +++ b/cpp/ql/test/successor-tests/initializer/aggregateinitializer/aggregateinitializer.c @@ -1,4 +1,4 @@ -void f() { - int a, b, c, d; - int x[] = { a + b, c - d }; -} +void f() { + int a, b, c, d; + int x[] = { a + b, c - d }; +} diff --git a/cpp/ql/test/successor-tests/initializer/constructorinitializer/constructorinitializer.cpp b/cpp/ql/test/successor-tests/initializer/constructorinitializer/constructorinitializer.cpp index adb3460317b..ce43dedf6ed 100644 --- a/cpp/ql/test/successor-tests/initializer/constructorinitializer/constructorinitializer.cpp +++ b/cpp/ql/test/successor-tests/initializer/constructorinitializer/constructorinitializer.cpp @@ -1,9 +1,9 @@ -class C { - public: - C(int x, int y); -}; - -void f() { - int i, j, k, l; - C c(i + j, k - l); -} +class C { + public: + C(int x, int y); +}; + +void f() { + int i, j, k, l; + C c(i + j, k - l); +} diff --git a/cpp/ql/test/successor-tests/initializer/initializer/initializer.c b/cpp/ql/test/successor-tests/initializer/initializer/initializer.c index 40204e94bf9..5cd9949f4c3 100644 --- a/cpp/ql/test/successor-tests/initializer/initializer/initializer.c +++ b/cpp/ql/test/successor-tests/initializer/initializer/initializer.c @@ -1,4 +1,4 @@ -void f() { - int a, b; - int i = a + b; +void f() { + int a, b; + int i = a + b; } \ No newline at end of file diff --git a/cpp/ql/test/successor-tests/initializer/parameterinitializer/parameterinitializer.cpp b/cpp/ql/test/successor-tests/initializer/parameterinitializer/parameterinitializer.cpp index 35ffb855f8a..d132cd810a0 100644 --- a/cpp/ql/test/successor-tests/initializer/parameterinitializer/parameterinitializer.cpp +++ b/cpp/ql/test/successor-tests/initializer/parameterinitializer/parameterinitializer.cpp @@ -1,31 +1,31 @@ -void printf(char *format, ...); - -int g(void) { - return 5; -} - -void f(int i = g()) { - printf("Got %d\n", i); -} - -class c { -public: - c(int j = g()) {}; - - void method(int k = g()) {}; -}; - -int main(void) { - f(3); - f(); - f(4); - f(); - - { - c my_c; - - my_c.method(); - } - - return 0; -} +void printf(char *format, ...); + +int g(void) { + return 5; +} + +void f(int i = g()) { + printf("Got %d\n", i); +} + +class c { +public: + c(int j = g()) {}; + + void method(int k = g()) {}; +}; + +int main(void) { + f(3); + f(); + f(4); + f(); + + { + c my_c; + + my_c.method(); + } + + return 0; +} diff --git a/cpp/ql/test/successor-tests/landexpr/landexpr.c b/cpp/ql/test/successor-tests/landexpr/landexpr.c index 90e62d1b58f..98fa0a23c6d 100644 --- a/cpp/ql/test/successor-tests/landexpr/landexpr.c +++ b/cpp/ql/test/successor-tests/landexpr/landexpr.c @@ -1,6 +1,6 @@ -void f() { - int a, b; - if (a && b) { - } - ; +void f() { + int a, b; + if (a && b) { + } + ; } \ No newline at end of file diff --git a/cpp/ql/test/successor-tests/lorexpr/lorexpr.c b/cpp/ql/test/successor-tests/lorexpr/lorexpr.c index 81e88d1ca27..d03d89760b6 100644 --- a/cpp/ql/test/successor-tests/lorexpr/lorexpr.c +++ b/cpp/ql/test/successor-tests/lorexpr/lorexpr.c @@ -1,6 +1,6 @@ -void f() { - int a, b; - if (a || b) { - } - ; +void f() { + int a, b; + if (a || b) { + } + ; } \ No newline at end of file diff --git a/cpp/ql/test/successor-tests/ltrbinopexpr/ltrbinopexpr.c b/cpp/ql/test/successor-tests/ltrbinopexpr/ltrbinopexpr.c index ad88c668f0f..cf093d36531 100644 --- a/cpp/ql/test/successor-tests/ltrbinopexpr/ltrbinopexpr.c +++ b/cpp/ql/test/successor-tests/ltrbinopexpr/ltrbinopexpr.c @@ -1,43 +1,43 @@ -void f() { - int i, j; - int* p, q; - - i + j; - i - j; - i * j; - i / j; - i % j; - - p + i; - p - i; - //q - p; - - i << j; - i >> j; - - i & j; - i | j; - i ^ j; - i == j; - i != j; - i > j; - i < j; - i >= j; - i <= j; - - i += j; - i -= j; - i *= j; - i /= j; - i %= j; - i <<= j; - i >>= j; - i &= j; - i |= j; - i ^= j; - - p += i; - p -= i; - - i, j; -} +void f() { + int i, j; + int* p, q; + + i + j; + i - j; + i * j; + i / j; + i % j; + + p + i; + p - i; + //q - p; + + i << j; + i >> j; + + i & j; + i | j; + i ^ j; + i == j; + i != j; + i > j; + i < j; + i >= j; + i <= j; + + i += j; + i -= j; + i *= j; + i /= j; + i %= j; + i <<= j; + i >>= j; + i &= j; + i |= j; + i ^= j; + + p += i; + p -= i; + + i, j; +} diff --git a/cpp/ql/test/successor-tests/newexpr/defconstructornewexpr/defconstructornewexpr.cpp b/cpp/ql/test/successor-tests/newexpr/defconstructornewexpr/defconstructornewexpr.cpp index b97b4c65383..0a51afb3b83 100644 --- a/cpp/ql/test/successor-tests/newexpr/defconstructornewexpr/defconstructornewexpr.cpp +++ b/cpp/ql/test/successor-tests/newexpr/defconstructornewexpr/defconstructornewexpr.cpp @@ -1,6 +1,6 @@ -class C { }; - -void f() { - new C; - return; +class C { }; + +void f() { + new C; + return; } \ No newline at end of file diff --git a/cpp/ql/test/successor-tests/newexpr/newexpr/newexpr.cpp b/cpp/ql/test/successor-tests/newexpr/newexpr/newexpr.cpp index cf27d3fea04..1060bfa898f 100644 --- a/cpp/ql/test/successor-tests/newexpr/newexpr/newexpr.cpp +++ b/cpp/ql/test/successor-tests/newexpr/newexpr/newexpr.cpp @@ -1,9 +1,9 @@ -class C { - public: - C(int i, int j); -}; - -void f() { - int a, b, c, d; - new C(a + b, c - d); -} +class C { + public: + C(int i, int j); +}; + +void f() { + int a, b, c, d; + new C(a + b, c - d); +} diff --git a/cpp/ql/test/successor-tests/questionexpr/questionexpr.c b/cpp/ql/test/successor-tests/questionexpr/questionexpr.c index d77accad443..aeb257d9a61 100644 --- a/cpp/ql/test/successor-tests/questionexpr/questionexpr.c +++ b/cpp/ql/test/successor-tests/questionexpr/questionexpr.c @@ -1,4 +1,4 @@ -void f() { - int a, b, c, d, x; - x = a == b ? c + b : d - b; +void f() { + int a, b, c, d, x; + x = a == b ? c + b : d - b; } \ No newline at end of file diff --git a/cpp/ql/test/successor-tests/returnstmt/returnstmt.c b/cpp/ql/test/successor-tests/returnstmt/returnstmt.c index e0383f5f336..f32c0632728 100644 --- a/cpp/ql/test/successor-tests/returnstmt/returnstmt.c +++ b/cpp/ql/test/successor-tests/returnstmt/returnstmt.c @@ -1,10 +1,10 @@ - -void return_void() { - return; - ; -} - -int return_int() { - return 1; - ; -} + +void return_void() { + return; + ; +} + +int return_int() { + return 1; + ; +} diff --git a/cpp/ql/test/successor-tests/staticlocals/staticlocals/staticlocals.cpp b/cpp/ql/test/successor-tests/staticlocals/staticlocals/staticlocals.cpp index 4420d4d05f6..f13e2fa9583 100644 --- a/cpp/ql/test/successor-tests/staticlocals/staticlocals/staticlocals.cpp +++ b/cpp/ql/test/successor-tests/staticlocals/staticlocals/staticlocals.cpp @@ -1,13 +1,13 @@ -int g() { - return 1; -} - -int h() { - return 1; -} - -void f() { - static int i = g(), j = h(); - static int k = g(); - ; -} +int g() { + return 1; +} + +int h() { + return 1; +} + +void f() { + static int i = g(), j = h(); + static int k = g(); + ; +} diff --git a/cpp/ql/test/successor-tests/subscriptexpr/subscriptexpr/revsubscriptexpr.c b/cpp/ql/test/successor-tests/subscriptexpr/subscriptexpr/revsubscriptexpr.c index 0850bf62ccf..f68a5bad0d9 100644 --- a/cpp/ql/test/successor-tests/subscriptexpr/subscriptexpr/revsubscriptexpr.c +++ b/cpp/ql/test/successor-tests/subscriptexpr/subscriptexpr/revsubscriptexpr.c @@ -1,5 +1,5 @@ -void g() { - double x[5]; - int i, a, b; - i = (a + b)[x]; -} +void g() { + double x[5]; + int i, a, b; + i = (a + b)[x]; +} diff --git a/cpp/ql/test/successor-tests/subscriptexpr/subscriptexpr/subscriptexpr.c b/cpp/ql/test/successor-tests/subscriptexpr/subscriptexpr/subscriptexpr.c index 22bed0c1afb..1a98c810aa7 100644 --- a/cpp/ql/test/successor-tests/subscriptexpr/subscriptexpr/subscriptexpr.c +++ b/cpp/ql/test/successor-tests/subscriptexpr/subscriptexpr/subscriptexpr.c @@ -1,5 +1,5 @@ -void f() { - double x[5]; - int i, a, b; - i = x[a + b]; -} +void f() { + double x[5]; + int i, a, b; + i = x[a + b]; +} diff --git a/cpp/ql/test/successor-tests/switchstmt/nodefaultswitchstmt/nodefaultswitchstmt.c b/cpp/ql/test/successor-tests/switchstmt/nodefaultswitchstmt/nodefaultswitchstmt.c index f12cd7d3620..bdd18c622e6 100644 --- a/cpp/ql/test/successor-tests/switchstmt/nodefaultswitchstmt/nodefaultswitchstmt.c +++ b/cpp/ql/test/successor-tests/switchstmt/nodefaultswitchstmt/nodefaultswitchstmt.c @@ -1,7 +1,7 @@ -void f(int x) { - switch (x) { - case 1: - case 2: - } - ; -} +void f(int x) { + switch (x) { + case 1: + case 2: + } + ; +} diff --git a/cpp/ql/test/successor-tests/switchstmt/switchstmt/switchstmt.c b/cpp/ql/test/successor-tests/switchstmt/switchstmt/switchstmt.c index 4f618a21e20..32be6e43b68 100644 --- a/cpp/ql/test/successor-tests/switchstmt/switchstmt/switchstmt.c +++ b/cpp/ql/test/successor-tests/switchstmt/switchstmt/switchstmt.c @@ -1,8 +1,8 @@ -void f(int x) { - switch (x) { - case 1: - case 2: - default: - } - ; -} +void f(int x) { + switch (x) { + case 1: + case 2: + default: + } + ; +} diff --git a/cpp/ql/test/successor-tests/unaryopexpr/unaryopexpr.c b/cpp/ql/test/successor-tests/unaryopexpr/unaryopexpr.c index 0d2ce20ab44..625be3434ee 100644 --- a/cpp/ql/test/successor-tests/unaryopexpr/unaryopexpr.c +++ b/cpp/ql/test/successor-tests/unaryopexpr/unaryopexpr.c @@ -1,14 +1,14 @@ -void f() { - int i; - &i; - - -i; - //+i - ~i; - !i; - - i++; - i--; - ++i; - --i; -} +void f() { + int i; + &i; + + -i; + //+i + ~i; + !i; + + i++; + i--; + ++i; + --i; +} diff --git a/cpp/ql/test/successor-tests/whilestmt/whilestmt.c b/cpp/ql/test/successor-tests/whilestmt/whilestmt.c index 02af4089e76..9de843ba20a 100644 --- a/cpp/ql/test/successor-tests/whilestmt/whilestmt.c +++ b/cpp/ql/test/successor-tests/whilestmt/whilestmt.c @@ -1,45 +1,45 @@ -void always_false_1() { - while(0) { - l1:; - } - l2:; -} - -void always_false_2() { - int done = 1; - while(!done) { - done = 0; - } -} - -void always_true_1() { - while(1) { - l1:; - break; - } - l2:; -} - -void always_true_2() { - while(1) { - l1:; - break; - l2:; - } - l3:; -} - -void always_true_3() { - while(1) { - l1:; - } - l2:; -} - -void normal() { - int i = 0; - while(i < 10) { - ++i; - } - l:; -} +void always_false_1() { + while(0) { + l1:; + } + l2:; +} + +void always_false_2() { + int done = 1; + while(!done) { + done = 0; + } +} + +void always_true_1() { + while(1) { + l1:; + break; + } + l2:; +} + +void always_true_2() { + while(1) { + l1:; + break; + l2:; + } + l3:; +} + +void always_true_3() { + while(1) { + l1:; + } + l2:; +} + +void normal() { + int i = 0; + while(i < 10) { + ++i; + } + l:; +} diff --git a/csharp/ql/src/plugin.xml b/csharp/ql/src/plugin.xml index f44185688ff..532f6c121ad 100644 --- a/csharp/ql/src/plugin.xml +++ b/csharp/ql/src/plugin.xml @@ -1,16 +1,16 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/csharp/ql/test/.project b/csharp/ql/test/.project index 1fa51e991e3..941c2e784d4 100644 --- a/csharp/ql/test/.project +++ b/csharp/ql/test/.project @@ -1,12 +1,12 @@ - - - semmlecode-csharp-tests - - - - - - - com.semmle.plugin.qdt.core.qlnature - - + + + semmlecode-csharp-tests + + + + + + + com.semmle.plugin.qdt.core.qlnature + + diff --git a/csharp/ql/test/library-tests/assemblies/Assembly1.cs_ b/csharp/ql/test/library-tests/assemblies/Assembly1.cs_ index 1e3f1b8c64e..e8484c4c377 100644 --- a/csharp/ql/test/library-tests/assemblies/Assembly1.cs_ +++ b/csharp/ql/test/library-tests/assemblies/Assembly1.cs_ @@ -1,20 +1,20 @@ -using System; - -namespace Assembly2 -{ - public delegate int del2(int x); - - public class Class2 : Attribute - { - } - - public class Class3 : Attribute - { - public class Class4 - { - } - public class Class5 - { - } - } -} +using System; + +namespace Assembly2 +{ + public delegate int del2(int x); + + public class Class2 : Attribute + { + } + + public class Class3 : Attribute + { + public class Class4 + { + } + public class Class5 + { + } + } +} diff --git a/csharp/ql/test/library-tests/assemblies/Assembly2.cs_ b/csharp/ql/test/library-tests/assemblies/Assembly2.cs_ index 4606901a5de..4d04c87acf6 100644 --- a/csharp/ql/test/library-tests/assemblies/Assembly2.cs_ +++ b/csharp/ql/test/library-tests/assemblies/Assembly2.cs_ @@ -1,23 +1,23 @@ -using System; -using Assembly2; - -namespace Assembly1 -{ - [Class3()] - public delegate Class2 del1(Class3 c3); - - [Class3()] - public class Class1 - { - [Class2()] - static public Class2 a; - static public Class2 b() { return new Class2(); } - [Class3()] - static public Class3.Class4 c(Class3 x) { return new Class3.Class4(); } - [Class2()] - static public int d() { return 1; } - static public del2 e() { return f; } - static public int f(int x) { return x; } - static public Class3.Class5 g(Class3.Class5 x) { return x; } - } -} +using System; +using Assembly2; + +namespace Assembly1 +{ + [Class3()] + public delegate Class2 del1(Class3 c3); + + [Class3()] + public class Class1 + { + [Class2()] + static public Class2 a; + static public Class2 b() { return new Class2(); } + [Class3()] + static public Class3.Class4 c(Class3 x) { return new Class3.Class4(); } + [Class2()] + static public int d() { return 1; } + static public del2 e() { return f; } + static public int f(int x) { return x; } + static public Class3.Class5 g(Class3.Class5 x) { return x; } + } +} diff --git a/csharp/ql/test/library-tests/generics/Generics20.expected b/csharp/ql/test/library-tests/generics/Generics20.expected index 78af767cb72..2a4f078a25f 100755 --- a/csharp/ql/test/library-tests/generics/Generics20.expected +++ b/csharp/ql/test/library-tests/generics/Generics20.expected @@ -1 +1 @@ -| 1 | +| 1 | diff --git a/csharp/ql/test/library-tests/standalone/controlflow/ControlFlow.cs b/csharp/ql/test/library-tests/standalone/controlflow/ControlFlow.cs index 56a6e5121cb..1dedc955c33 100644 --- a/csharp/ql/test/library-tests/standalone/controlflow/ControlFlow.cs +++ b/csharp/ql/test/library-tests/standalone/controlflow/ControlFlow.cs @@ -1,14 +1,14 @@ -// semmle-extractor-options: --standalone - -using System; - -class Cfg -{ - void F() - { - var v = new InvalidType(); - Debug.Assert(v.a.b, "This is true"); - - new CounterCreationData() { CounterHelp = string.Empty, CounterType = v.Type }; - } -} +// semmle-extractor-options: --standalone + +using System; + +class Cfg +{ + void F() + { + var v = new InvalidType(); + Debug.Assert(v.a.b, "This is true"); + + new CounterCreationData() { CounterHelp = string.Empty, CounterType = v.Type }; + } +} diff --git a/csharp/ql/test/library-tests/tokens/Tokens1.expected b/csharp/ql/test/library-tests/tokens/Tokens1.expected index 3956fb2ce93..0ed42634419 100644 --- a/csharp/ql/test/library-tests/tokens/Tokens1.expected +++ b/csharp/ql/test/library-tests/tokens/Tokens1.expected @@ -1,3 +1,3 @@ -| tokens.cs:5:15:5:17 | I1 | -| tokens.cs:10:12:10:14 | S1 | -| tokens.cs:14:11:14:13 | C1 | +| tokens.cs:5:15:5:17 | I1 | +| tokens.cs:10:12:10:14 | S1 | +| tokens.cs:14:11:14:13 | C1 | diff --git a/csharp/ql/test/query-tests/ReadOnlyContainer/ReadOnlyContainer.expected b/csharp/ql/test/query-tests/ReadOnlyContainer/ReadOnlyContainer.expected index 98b43cffc28..39e5f5e9628 100755 --- a/csharp/ql/test/query-tests/ReadOnlyContainer/ReadOnlyContainer.expected +++ b/csharp/ql/test/query-tests/ReadOnlyContainer/ReadOnlyContainer.expected @@ -1,11 +1,11 @@ -| ReadOnlyContainer.cs:9:16:9:17 | v1 | The contents of this container are never initialized. | -| ReadOnlyContainer.cs:13:13:13:14 | v2 | The contents of this container are never initialized. | -| ReadOnlyContainer.cs:30:16:30:17 | v3 | The contents of this container are never initialized. | -| ReadOnlyContainer.cs:55:13:55:14 | v4 | The contents of this container are never initialized. | -| ReadOnlyContainer.cs:76:13:76:14 | v5 | The contents of this container are never initialized. | -| ReadOnlyContainer.cs:82:13:82:14 | v6 | The contents of this container are never initialized. | -| ReadOnlyContainer.cs:88:13:88:14 | v7 | The contents of this container are never initialized. | -| ReadOnlyContainer.cs:91:13:91:14 | v8 | The contents of this container are never initialized. | -| ReadOnlyContainer.cs:96:13:96:14 | v9 | The contents of this container are never initialized. | -| ReadOnlyContainer.cs:99:13:99:15 | v10 | The contents of this container are never initialized. | +| ReadOnlyContainer.cs:9:16:9:17 | v1 | The contents of this container are never initialized. | +| ReadOnlyContainer.cs:13:13:13:14 | v2 | The contents of this container are never initialized. | +| ReadOnlyContainer.cs:30:16:30:17 | v3 | The contents of this container are never initialized. | +| ReadOnlyContainer.cs:55:13:55:14 | v4 | The contents of this container are never initialized. | +| ReadOnlyContainer.cs:76:13:76:14 | v5 | The contents of this container are never initialized. | +| ReadOnlyContainer.cs:82:13:82:14 | v6 | The contents of this container are never initialized. | +| ReadOnlyContainer.cs:88:13:88:14 | v7 | The contents of this container are never initialized. | +| ReadOnlyContainer.cs:91:13:91:14 | v8 | The contents of this container are never initialized. | +| ReadOnlyContainer.cs:96:13:96:14 | v9 | The contents of this container are never initialized. | +| ReadOnlyContainer.cs:99:13:99:15 | v10 | The contents of this container are never initialized. | | ReadOnlyContainer.cs:121:13:121:15 | v11 | The contents of this container are never initialized. | \ No newline at end of file diff --git a/docs/ql-style-guide.md b/docs/ql-style-guide.md index ad30770944d..2e2f8eb39f7 100644 --- a/docs/ql-style-guide.md +++ b/docs/ql-style-guide.md @@ -1,417 +1,417 @@ -# QL Style Guide - -## Introduction - -This document describes how to format the QL code you contribute to this repository. It covers aspects such as layout, white-space, naming and documentation. Adhering to consistent standards makes code easier to read and maintain. Of course, these are only guidelines, and can be overridden as the need arises on a case-by-case basis. Where existing code deviates from these guidelines, prefer consistency with the surrounding code. - -Words in *italic* are defined in the [Glossary](#glossary). - -## Indentation -1. *Always* use 2 spaces for indentation. -1. *Always* indent: - - The *body* of a module, newtype, class or predicate - - The second and subsequent lines after you use a line break to split a long line - - The *body* of a `from`, `where` or `select` clause where it spans multiple lines - - The *body* of a *quantifier* that spans multiple lines - - -### Examples - -```ql -module Helpers { - /** ... */ - class X ... { - /** ... */ - int getNumberOfChildren () { - result = count(int child | - exists(this.getChild(child)) - ) - } - } -} -``` - -```ql -from Call c, string reason -where isDeprecated(c, reason) -select c, "This call to '$@' is deprecated because " + reason + ".", - c.getTarget(), c.getTarget().getName() -``` - -## Line breaks -1. Use UNIX line endings. -1. Lines *must not* exceed 100 characters. -1. Long lines *should* be split with a line break, and the following lines *must* be indented one level until the next "regular" line break. -1. There *should* be a single blank line: - - Between the file documentation and the first `import` - - Before each declaration, except for the first declaration in a *body* - - Before the `from`-`where`-`select` section in a query file -1. *Avoid* two or more adjacent blank lines. -1. There *must* be a new line after the *annotations* `cached`, `pragma`, `language` and `bindingset`. Other *annotations* do not have a new line. -1. There *should not* be additional blank lines within a predicate. -1. There *may* be a new line: - - Immediately after the `from`, `where` or `select` keywords in a query. - - Immediately after `if`, `then`, or `else` keywords. The `then` and `else` parts *should* be consistent. -1. *Avoid* other line breaks in declarations, other than to break long lines. -1. When operands of *binary operators* span two lines, the operator *should* be placed at the end of the first line. - -### Examples - -```ql -cached -private int getNumberOfParameters() { - ... -} -``` - -```ql -predicate methodStats(string qualifiedName, string name, - int numberOfParameters, int numberOfStatements, int numberOfExpressions, - int linesOfCode, int nestingDepth, int numberOfBranches) { - ... -} -``` - -```ql -from Method main -where main.getName() = "Main" -select main, "This is the program entry point." -``` - -```ql -from Method main -where - main.getName() = "Main" and - main.getNumberOfParameters() = 0 -select main, "Main method has no parameters." -``` - -```ql - if x.isPublic() - then result = "public" - else result = "private" -``` - -```ql - if x.isPublic() then - result = "public" - else - result = "private" -``` - -```ql - if - x.isPublic() - then - result = "public" - else - result = "private" -``` - -## Braces -1. Braces follow [Stroustrup](https://en.wikipedia.org/wiki/Indentation_style#Variant:_Stroustrup) style. The opening `{` *must* be placed at the end of the preceding line. -1. The closing `}` *must* be placed on its own line, indented to the outer level, or be on the same line as the opening `{`. -1. Braces of empty blocks *may* be placed on a single line, with a single space separating the braces. -1. Short predicates, not exceeding the maximum line width, *may* be placed on a single line, with a space following the opening brace and preceding the closing brace. - -### Examples - -```ql -class ThrowException extends ThrowExpr { - Foo() { - this.getTarget() instanceof ExceptionClass - } - - override string toString() { result = "Throw Exception" } -} -``` - -## Spaces -1. There *must* be a space or line break: - - Surrounding each `=` and `|` - - After each `,` -1. There *should* be a space or line break: - - Surrounding each *binary operator*, which *must* be balanced - - Surrounding `..` in a range - - Exceptions to this may be made to save space or to improve readability. -1. *Avoid* other spaces, for example: - - After a *quantifier/aggregation* keyword - - After the predicate name in a *call* - - Inside brackets used for *calls*, single-line quantifiers, and parenthesised formulas - - Surrounding a `.` - - Inside the opening or closing `[ ]` in a range expression - - Inside casts `a.(X)` -1. *Avoid* multiple spaces, except for indentation, and *avoid* additional indentation to align formulas, parameters or arguments. -1. *Do not* put whitespace on blank lines, or trailing on the end of a line. -1. *Do not* use tabs. - - -### Examples - -```ql -cached -private predicate foo(Expr e, Expr p) { - exists(int n | - n in [0 .. 1] | - e = p.getChild(n + 1) - ) -} -``` - -## Naming -1. Use [PascalCase](http://wiki.c2.com/?PascalCase) for: - - `class` names - - `module` names - - `newtype` names -1. Use [camelCase](https://en.wikipedia.org/wiki/Camel_case) for: - - Predicate names - - Variable names -1. Newtype predicate names *should* begin with `T`. -1. Predicates that have a result *should* be named `get...` -1. Predicates that can return multiple results *should* be named `getA...` or `getAn...` -1. Predicates that don't have a result or parameters *should* be named `is...` or `has...` -1. *Avoid* underscores in names. -1. *Avoid* short or single-letter names for classes, predicates and fields. -1. Short or single letter names for parameters and *quantifiers* *may* be used provided that they are sufficiently clear. -1. Use names as they are used in the target-language specification. -1. Use American English. - -### Examples - -```ql -/** ... */ -predicate calls(Callable caller, Callable callee) { - ... -} -``` - -```ql -/** ... */ -class Type extends ... { - /** ... */ - string getName() { ... } - - /** ... */ - predicate declares(Member m) { ... } - - /** ... */ - predicate isGeneric() { ... } - - /** ... */ - Type getTypeParameter(int n) { ... } - - /** ... */ - Type getATypeParameter() { ... } -} -``` - -## Documentation - -General requirements: - -1. Documentation *must* adhere to the [QLDoc specification](https://help.semmle.com/QL/QLDocSpecification.html). -1. Use `/** ... */` for documentation, even for single line comments. -1. For single-line documentation, the `/**` and `*/` are written on the same line as the comment. -1. For multi-line documentation, the `/**` and `*/` are written on separate lines. There is a `*` preceding each comment line, aligned on the first `*`. -1. Use full sentences, with capital letters and full stops. -1. Use American English. -1. Documentation comments *should* be appropriate for users of the code. -1. Documentation for maintainers of the code *must* use normal comments. - -Documentation for specific items: - -1. Public declarations *must* be documented. -1. Non-public declarations *should* be documented. -1. Declarations in query files *should* be documented. -1. Library files (`.qll` files) *should* be have a documentation comment at the top of the file. -1. Query files, except for tests, *must* have a QLDoc query documentation comment at the top of the file. -1. Predicates that do not have a result *should* be documented `/** Holds if ... */` -1. Predicates that have a result *should* be documented `/** Gets ... */` -1. All predicate parameters *should* be referred to in the predicate documentation. -1. Reference names, such as types and parameters, using backticks `` ` ``. -1. Give examples of code in the target language, enclosed in ```` ``` ```` or `` ` ``. -1. Classes *should* be documented in the singular, for example `/* An expression. */` -1. Where a class denotes a generic concept with subclasses, list those subclasses. -1. Declarations that are deprecated *should* be documented as `DEPRECATED: ...` -1. Declarations that are for internal use *should* be documented as `INTERNAL: Do not use`. - -### Examples - -```ql -/** Provides logic for determining constant expressions. */ -``` - -```ql -/** - * Holds if the qualifier of this call has type `qualifierType`. - * `isExactType` indicates whether the type is exact, that is, whether - * the qualifier is guaranteed not to be a subtype of `qualifierType`. - */ -``` -```ql -/** - * A delegate declaration, for example - * ``` - * delegate void Logger(string text); - * ``` - */ -class Delegate extends ... -``` - -```ql -/** - * An element that can be called. - * - * Either a method (`Method`), a constructor (`Constructor`), a destructor - * (`Destructor`), an operator (`Operator`), an accessor (`Accessor`), - * an anonymous function (`AnonymousFunctionExpr`), or a local function - * (`LocalFunction`). - */ -class Callable extends ... -``` - -```ql -/** DEPRECATED: Use `getAnExpr()` instead. */ -deprecated Expr getInitializer() -``` - -```ql -/** - * INTERNAL: Do not use. - */ -``` - -## Formulas -1. *Prefer* one *conjunct* per line. -1. Write the `and` at the end of the line. This also applies in `where` clauses. -1. *Prefer* to write the `or` keyword on its own line. -1. The `or` keyword *may* be written at the end of a line, or within a line, provided that it has no unparenthesised `and` operands. -1. Single-line formulas *may* be used in order to save space or add clarity, particularly in the *body* of a *quantifier/aggregation*. -1. *Always* use brackets to clarify the precedence of: - - `implies` - - `if`-`then`-`else` -1. Parenthesised formulas *can* be written: - - Within a single line. There *should not* be an additional space following the opening parenthesis or preceding the closing parenthesis. - - Spanning multiple lines. The opening parenthesis *should* be placed at the end of the preceding line, the body should be indented one level, and the closing bracket should be placed on a new line at the outer indentation. -1. *Quantifiers/aggregations* *can* be written: - - Within a single line. In this case, there is no space to the inside of the parentheses, or after the quantifier keyword. - - Across multiple lines. In this case, type declarations are on the same line as the quantifier, the `|` *may* be at the end of the line, or *may* be on its own line, and the body of the quantifier *must* be indented one level. The closing `)` is written on a new line, at the outer indentation. -1. `if`-`then`-`else` *can* be written: - - On a single line - - With the *body* after the `if`/`then`/`else` keyword - - With the *body* indented on the next line - - *Always* parenthesise the `else` part if it is a compound formula. -1. The `and` and `else` keywords *may* be placed on the same line as the closing parenthesis. -1. The `and` and `else` keywords *may* be "cuddled": `) else (` -1. *Always* qualify *calls* to predicates of the same class with `this`. -2. *Prefer* postfix casts `a.(Expr)` to prefix casts `(Expr)a`. - -### Examples - -```ql - argumentType.isImplicitlyConvertibleTo(parameterType) - or - argumentType instanceof NullType and - result.getParameter(i).isOut() and - parameterType instanceof SimpleType - or - reflectionOrDynamicArg(argumentType, parameterType) -``` - -```ql - this.getName() = "Finalize" and not exists(this.getAParameter()) -``` - -```ql - e1.getType() instanceof BoolType and ( - b1 = true - or - b1 = false - ) and ( - b2 = true - or - b2 = false - ) -``` - -```ql - if e1 instanceof BitwiseOrExpr or e1 instanceof LogicalOrExpr then ( - impliesSub(e1.(BinaryOperation).getAnOperand(), e2, b1, b2) and - b1 = false - ) else ( - e1.getType() instanceof BoolType and - e1 = e2 and - b1 = b2 and - (b1 = true or b1 = false) - ) -``` - -```ql - (x instanceof Exception implies x.isPublic()) and y instanceof Exception -``` - -```ql - x instanceof Exception implies (x.isPublic() and y instanceof Exception) -``` - -```ql - exists(Type arg | arg = this.getAChild() | arg instanceof TypeParameter) -``` - -```ql - exists(Type qualifierType | - this.hasNonExactQualifierType(qualifierType) | - result = getANonExactQualifierSubType(qualifierType) - ) -``` - -```ql - methods = count(Method m | t = m.getDeclaringType() and not ilc(m)) -``` - -```ql - if n = 0 then result = 1 else result = n * f(n - 1) -``` - -```ql - if n = 0 - then result = 1 - else result = n * f(n - 1) -``` - -```ql - if - n = 0 - then - result = 1 - else - result = n * f(n - 1) -``` - -```ql - if exists(this.getContainingType()) then ( - result = "A nested class" and - parentName = this.getContainingType().getFullyQualifiedName() - ) else ( - result = parentName + "." + this.getName() and - parentName = this.getNamespace().getFullyQualifiedName() - ) -``` - -## Glossary - -| Phrase | Meaning | -|-------------|----------| -| *[annotation](https://help.semmle.com/QL/QLLanguageSpecification.html#annotations)* | An additional specifier used to modify a declaration, such as `private`, `override`, `deprecated`, `pragma`, `bindingset`, or `cached`. | -| *body* | The text inside `{ }`, `( )`, or each section of an `if`-`then`-`else` or `from`-`where`-`select`. | -| *binary operator* | An operator with two operands, such as comparison operators, `and`, `or`, `implies`, or arithmetic operators. | -| *call* | A *formula* that invokes a predicate, e.g. `this.isStatic()` or `calls(a,b)`. | -| *[conjunct](https://help.semmle.com/QL/QLLanguageSpecification.html#conjunctions)* | A formula that is an operand to an `and`. | -| *declaration* | A class, module, predicate, field or newtype. | -| *[disjunct](https://help.semmle.com/QL/QLLanguageSpecification.html#disjunctions)* | A formula that is an operand to an `or`. | -| *[formula](https://help.semmle.com/QL/QLLanguageSpecification.html#formulas)* | A logical expression, such as `A = B`, a *call*, a *quantifier*, `and`, `or`, `not`, `in` or `instanceof`. | -| *should/should not/avoid/prefer* | Adhere to this rule wherever possible, where it makes sense. | -| *may/can* | This is a reasonable alternative, to be used with discretion. | -| *must/always/do not* | Always adhere to this rule. | -| *[quantifier/aggregation](https://help.semmle.com/QL/QLLanguageSpecification.html#aggregations)* | `exists`, `count`, `strictcount`, `any`, `forall`, `forex` and so on. | -| *variable* | A parameter to a predicate, a field, a from variable, or a variable introduced by a *quantifier* or *aggregation*. | +# QL Style Guide + +## Introduction + +This document describes how to format the QL code you contribute to this repository. It covers aspects such as layout, white-space, naming and documentation. Adhering to consistent standards makes code easier to read and maintain. Of course, these are only guidelines, and can be overridden as the need arises on a case-by-case basis. Where existing code deviates from these guidelines, prefer consistency with the surrounding code. + +Words in *italic* are defined in the [Glossary](#glossary). + +## Indentation +1. *Always* use 2 spaces for indentation. +1. *Always* indent: + - The *body* of a module, newtype, class or predicate + - The second and subsequent lines after you use a line break to split a long line + - The *body* of a `from`, `where` or `select` clause where it spans multiple lines + - The *body* of a *quantifier* that spans multiple lines + + +### Examples + +```ql +module Helpers { + /** ... */ + class X ... { + /** ... */ + int getNumberOfChildren () { + result = count(int child | + exists(this.getChild(child)) + ) + } + } +} +``` + +```ql +from Call c, string reason +where isDeprecated(c, reason) +select c, "This call to '$@' is deprecated because " + reason + ".", + c.getTarget(), c.getTarget().getName() +``` + +## Line breaks +1. Use UNIX line endings. +1. Lines *must not* exceed 100 characters. +1. Long lines *should* be split with a line break, and the following lines *must* be indented one level until the next "regular" line break. +1. There *should* be a single blank line: + - Between the file documentation and the first `import` + - Before each declaration, except for the first declaration in a *body* + - Before the `from`-`where`-`select` section in a query file +1. *Avoid* two or more adjacent blank lines. +1. There *must* be a new line after the *annotations* `cached`, `pragma`, `language` and `bindingset`. Other *annotations* do not have a new line. +1. There *should not* be additional blank lines within a predicate. +1. There *may* be a new line: + - Immediately after the `from`, `where` or `select` keywords in a query. + - Immediately after `if`, `then`, or `else` keywords. The `then` and `else` parts *should* be consistent. +1. *Avoid* other line breaks in declarations, other than to break long lines. +1. When operands of *binary operators* span two lines, the operator *should* be placed at the end of the first line. + +### Examples + +```ql +cached +private int getNumberOfParameters() { + ... +} +``` + +```ql +predicate methodStats(string qualifiedName, string name, + int numberOfParameters, int numberOfStatements, int numberOfExpressions, + int linesOfCode, int nestingDepth, int numberOfBranches) { + ... +} +``` + +```ql +from Method main +where main.getName() = "Main" +select main, "This is the program entry point." +``` + +```ql +from Method main +where + main.getName() = "Main" and + main.getNumberOfParameters() = 0 +select main, "Main method has no parameters." +``` + +```ql + if x.isPublic() + then result = "public" + else result = "private" +``` + +```ql + if x.isPublic() then + result = "public" + else + result = "private" +``` + +```ql + if + x.isPublic() + then + result = "public" + else + result = "private" +``` + +## Braces +1. Braces follow [Stroustrup](https://en.wikipedia.org/wiki/Indentation_style#Variant:_Stroustrup) style. The opening `{` *must* be placed at the end of the preceding line. +1. The closing `}` *must* be placed on its own line, indented to the outer level, or be on the same line as the opening `{`. +1. Braces of empty blocks *may* be placed on a single line, with a single space separating the braces. +1. Short predicates, not exceeding the maximum line width, *may* be placed on a single line, with a space following the opening brace and preceding the closing brace. + +### Examples + +```ql +class ThrowException extends ThrowExpr { + Foo() { + this.getTarget() instanceof ExceptionClass + } + + override string toString() { result = "Throw Exception" } +} +``` + +## Spaces +1. There *must* be a space or line break: + - Surrounding each `=` and `|` + - After each `,` +1. There *should* be a space or line break: + - Surrounding each *binary operator*, which *must* be balanced + - Surrounding `..` in a range + - Exceptions to this may be made to save space or to improve readability. +1. *Avoid* other spaces, for example: + - After a *quantifier/aggregation* keyword + - After the predicate name in a *call* + - Inside brackets used for *calls*, single-line quantifiers, and parenthesised formulas + - Surrounding a `.` + - Inside the opening or closing `[ ]` in a range expression + - Inside casts `a.(X)` +1. *Avoid* multiple spaces, except for indentation, and *avoid* additional indentation to align formulas, parameters or arguments. +1. *Do not* put whitespace on blank lines, or trailing on the end of a line. +1. *Do not* use tabs. + + +### Examples + +```ql +cached +private predicate foo(Expr e, Expr p) { + exists(int n | + n in [0 .. 1] | + e = p.getChild(n + 1) + ) +} +``` + +## Naming +1. Use [PascalCase](http://wiki.c2.com/?PascalCase) for: + - `class` names + - `module` names + - `newtype` names +1. Use [camelCase](https://en.wikipedia.org/wiki/Camel_case) for: + - Predicate names + - Variable names +1. Newtype predicate names *should* begin with `T`. +1. Predicates that have a result *should* be named `get...` +1. Predicates that can return multiple results *should* be named `getA...` or `getAn...` +1. Predicates that don't have a result or parameters *should* be named `is...` or `has...` +1. *Avoid* underscores in names. +1. *Avoid* short or single-letter names for classes, predicates and fields. +1. Short or single letter names for parameters and *quantifiers* *may* be used provided that they are sufficiently clear. +1. Use names as they are used in the target-language specification. +1. Use American English. + +### Examples + +```ql +/** ... */ +predicate calls(Callable caller, Callable callee) { + ... +} +``` + +```ql +/** ... */ +class Type extends ... { + /** ... */ + string getName() { ... } + + /** ... */ + predicate declares(Member m) { ... } + + /** ... */ + predicate isGeneric() { ... } + + /** ... */ + Type getTypeParameter(int n) { ... } + + /** ... */ + Type getATypeParameter() { ... } +} +``` + +## Documentation + +General requirements: + +1. Documentation *must* adhere to the [QLDoc specification](https://help.semmle.com/QL/QLDocSpecification.html). +1. Use `/** ... */` for documentation, even for single line comments. +1. For single-line documentation, the `/**` and `*/` are written on the same line as the comment. +1. For multi-line documentation, the `/**` and `*/` are written on separate lines. There is a `*` preceding each comment line, aligned on the first `*`. +1. Use full sentences, with capital letters and full stops. +1. Use American English. +1. Documentation comments *should* be appropriate for users of the code. +1. Documentation for maintainers of the code *must* use normal comments. + +Documentation for specific items: + +1. Public declarations *must* be documented. +1. Non-public declarations *should* be documented. +1. Declarations in query files *should* be documented. +1. Library files (`.qll` files) *should* be have a documentation comment at the top of the file. +1. Query files, except for tests, *must* have a QLDoc query documentation comment at the top of the file. +1. Predicates that do not have a result *should* be documented `/** Holds if ... */` +1. Predicates that have a result *should* be documented `/** Gets ... */` +1. All predicate parameters *should* be referred to in the predicate documentation. +1. Reference names, such as types and parameters, using backticks `` ` ``. +1. Give examples of code in the target language, enclosed in ```` ``` ```` or `` ` ``. +1. Classes *should* be documented in the singular, for example `/* An expression. */` +1. Where a class denotes a generic concept with subclasses, list those subclasses. +1. Declarations that are deprecated *should* be documented as `DEPRECATED: ...` +1. Declarations that are for internal use *should* be documented as `INTERNAL: Do not use`. + +### Examples + +```ql +/** Provides logic for determining constant expressions. */ +``` + +```ql +/** + * Holds if the qualifier of this call has type `qualifierType`. + * `isExactType` indicates whether the type is exact, that is, whether + * the qualifier is guaranteed not to be a subtype of `qualifierType`. + */ +``` +```ql +/** + * A delegate declaration, for example + * ``` + * delegate void Logger(string text); + * ``` + */ +class Delegate extends ... +``` + +```ql +/** + * An element that can be called. + * + * Either a method (`Method`), a constructor (`Constructor`), a destructor + * (`Destructor`), an operator (`Operator`), an accessor (`Accessor`), + * an anonymous function (`AnonymousFunctionExpr`), or a local function + * (`LocalFunction`). + */ +class Callable extends ... +``` + +```ql +/** DEPRECATED: Use `getAnExpr()` instead. */ +deprecated Expr getInitializer() +``` + +```ql +/** + * INTERNAL: Do not use. + */ +``` + +## Formulas +1. *Prefer* one *conjunct* per line. +1. Write the `and` at the end of the line. This also applies in `where` clauses. +1. *Prefer* to write the `or` keyword on its own line. +1. The `or` keyword *may* be written at the end of a line, or within a line, provided that it has no unparenthesised `and` operands. +1. Single-line formulas *may* be used in order to save space or add clarity, particularly in the *body* of a *quantifier/aggregation*. +1. *Always* use brackets to clarify the precedence of: + - `implies` + - `if`-`then`-`else` +1. Parenthesised formulas *can* be written: + - Within a single line. There *should not* be an additional space following the opening parenthesis or preceding the closing parenthesis. + - Spanning multiple lines. The opening parenthesis *should* be placed at the end of the preceding line, the body should be indented one level, and the closing bracket should be placed on a new line at the outer indentation. +1. *Quantifiers/aggregations* *can* be written: + - Within a single line. In this case, there is no space to the inside of the parentheses, or after the quantifier keyword. + - Across multiple lines. In this case, type declarations are on the same line as the quantifier, the `|` *may* be at the end of the line, or *may* be on its own line, and the body of the quantifier *must* be indented one level. The closing `)` is written on a new line, at the outer indentation. +1. `if`-`then`-`else` *can* be written: + - On a single line + - With the *body* after the `if`/`then`/`else` keyword + - With the *body* indented on the next line + - *Always* parenthesise the `else` part if it is a compound formula. +1. The `and` and `else` keywords *may* be placed on the same line as the closing parenthesis. +1. The `and` and `else` keywords *may* be "cuddled": `) else (` +1. *Always* qualify *calls* to predicates of the same class with `this`. +2. *Prefer* postfix casts `a.(Expr)` to prefix casts `(Expr)a`. + +### Examples + +```ql + argumentType.isImplicitlyConvertibleTo(parameterType) + or + argumentType instanceof NullType and + result.getParameter(i).isOut() and + parameterType instanceof SimpleType + or + reflectionOrDynamicArg(argumentType, parameterType) +``` + +```ql + this.getName() = "Finalize" and not exists(this.getAParameter()) +``` + +```ql + e1.getType() instanceof BoolType and ( + b1 = true + or + b1 = false + ) and ( + b2 = true + or + b2 = false + ) +``` + +```ql + if e1 instanceof BitwiseOrExpr or e1 instanceof LogicalOrExpr then ( + impliesSub(e1.(BinaryOperation).getAnOperand(), e2, b1, b2) and + b1 = false + ) else ( + e1.getType() instanceof BoolType and + e1 = e2 and + b1 = b2 and + (b1 = true or b1 = false) + ) +``` + +```ql + (x instanceof Exception implies x.isPublic()) and y instanceof Exception +``` + +```ql + x instanceof Exception implies (x.isPublic() and y instanceof Exception) +``` + +```ql + exists(Type arg | arg = this.getAChild() | arg instanceof TypeParameter) +``` + +```ql + exists(Type qualifierType | + this.hasNonExactQualifierType(qualifierType) | + result = getANonExactQualifierSubType(qualifierType) + ) +``` + +```ql + methods = count(Method m | t = m.getDeclaringType() and not ilc(m)) +``` + +```ql + if n = 0 then result = 1 else result = n * f(n - 1) +``` + +```ql + if n = 0 + then result = 1 + else result = n * f(n - 1) +``` + +```ql + if + n = 0 + then + result = 1 + else + result = n * f(n - 1) +``` + +```ql + if exists(this.getContainingType()) then ( + result = "A nested class" and + parentName = this.getContainingType().getFullyQualifiedName() + ) else ( + result = parentName + "." + this.getName() and + parentName = this.getNamespace().getFullyQualifiedName() + ) +``` + +## Glossary + +| Phrase | Meaning | +|-------------|----------| +| *[annotation](https://help.semmle.com/QL/QLLanguageSpecification.html#annotations)* | An additional specifier used to modify a declaration, such as `private`, `override`, `deprecated`, `pragma`, `bindingset`, or `cached`. | +| *body* | The text inside `{ }`, `( )`, or each section of an `if`-`then`-`else` or `from`-`where`-`select`. | +| *binary operator* | An operator with two operands, such as comparison operators, `and`, `or`, `implies`, or arithmetic operators. | +| *call* | A *formula* that invokes a predicate, e.g. `this.isStatic()` or `calls(a,b)`. | +| *[conjunct](https://help.semmle.com/QL/QLLanguageSpecification.html#conjunctions)* | A formula that is an operand to an `and`. | +| *declaration* | A class, module, predicate, field or newtype. | +| *[disjunct](https://help.semmle.com/QL/QLLanguageSpecification.html#disjunctions)* | A formula that is an operand to an `or`. | +| *[formula](https://help.semmle.com/QL/QLLanguageSpecification.html#formulas)* | A logical expression, such as `A = B`, a *call*, a *quantifier*, `and`, `or`, `not`, `in` or `instanceof`. | +| *should/should not/avoid/prefer* | Adhere to this rule wherever possible, where it makes sense. | +| *may/can* | This is a reasonable alternative, to be used with discretion. | +| *must/always/do not* | Always adhere to this rule. | +| *[quantifier/aggregation](https://help.semmle.com/QL/QLLanguageSpecification.html#aggregations)* | `exists`, `count`, `strictcount`, `any`, `forall`, `forex` and so on. | +| *variable* | A parameter to a predicate, a field, a from variable, or a variable introduced by a *quantifier* or *aggregation*. | diff --git a/java/ql/src/.settings/org.eclipse.jdt.core.prefs b/java/ql/src/.settings/org.eclipse.jdt.core.prefs index 860376bf985..b36152aea39 100644 --- a/java/ql/src/.settings/org.eclipse.jdt.core.prefs +++ b/java/ql/src/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,7 @@ -#Tue Nov 04 11:42:37 GMT 2008 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 -org.eclipse.jdt.core.compiler.compliance=1.5 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.5 +#Tue Nov 04 11:42:37 GMT 2008 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/MissingParentBean.xml b/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/MissingParentBean.xml index 9e7554e5254..6ed09e2920e 100644 --- a/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/MissingParentBean.xml +++ b/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/MissingParentBean.xml @@ -1,28 +1,28 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/TooManyBeans.xml b/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/TooManyBeans.xml index bd8b0ad7da1..0361ff562c0 100644 --- a/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/TooManyBeans.xml +++ b/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/TooManyBeans.xml @@ -1,8 +1,8 @@ - - - - - - - - + + + + + + + + diff --git a/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/UnusedBean.xml b/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/UnusedBean.xml index e40477b83c8..39ef911a3e6 100644 --- a/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/UnusedBean.xml +++ b/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/UnusedBean.xml @@ -1,6 +1,6 @@ - - - - - - + + + + + + diff --git a/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/UselessPropertyOverride.xml b/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/UselessPropertyOverride.xml index 9337a0f045d..9a8cceaf3dc 100644 --- a/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/UselessPropertyOverride.xml +++ b/java/ql/src/Frameworks/Spring/Architecture/Refactoring Opportunities/UselessPropertyOverride.xml @@ -1,23 +1,23 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/java/ql/src/Frameworks/Spring/Violations of Best Practice/AvoidAutowiring.xml b/java/ql/src/Frameworks/Spring/Violations of Best Practice/AvoidAutowiring.xml index e7f707bdb65..2a10a0be651 100644 --- a/java/ql/src/Frameworks/Spring/Violations of Best Practice/AvoidAutowiring.xml +++ b/java/ql/src/Frameworks/Spring/Violations of Best Practice/AvoidAutowiring.xml @@ -1,13 +1,13 @@ - - - - - - - - + + + + + + + + \ No newline at end of file diff --git a/java/ql/src/Frameworks/Spring/Violations of Best Practice/DontUseConstructorArgIndex.xml b/java/ql/src/Frameworks/Spring/Violations of Best Practice/DontUseConstructorArgIndex.xml index 3e14a36dbce..92560855a7c 100644 --- a/java/ql/src/Frameworks/Spring/Violations of Best Practice/DontUseConstructorArgIndex.xml +++ b/java/ql/src/Frameworks/Spring/Violations of Best Practice/DontUseConstructorArgIndex.xml @@ -1,13 +1,13 @@ - - - - - - - - - - + + + + + + + + + + \ No newline at end of file diff --git a/java/ql/src/Frameworks/Spring/Violations of Best Practice/ImportsFirst.xml b/java/ql/src/Frameworks/Spring/Violations of Best Practice/ImportsFirst.xml index 739e375f28c..1199bb4de0e 100644 --- a/java/ql/src/Frameworks/Spring/Violations of Best Practice/ImportsFirst.xml +++ b/java/ql/src/Frameworks/Spring/Violations of Best Practice/ImportsFirst.xml @@ -1,26 +1,26 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/ql/src/Frameworks/Spring/Violations of Best Practice/NoBeanDescription.xml b/java/ql/src/Frameworks/Spring/Violations of Best Practice/NoBeanDescription.xml index 438d11b4449..7d6af942ca4 100644 --- a/java/ql/src/Frameworks/Spring/Violations of Best Practice/NoBeanDescription.xml +++ b/java/ql/src/Frameworks/Spring/Violations of Best Practice/NoBeanDescription.xml @@ -1,27 +1,27 @@ - - - - This file configures the various service beans. - - - - - - This bean defines base properties common to the service beans - - ... - - - - ... - - - - ... - + + + + This file configures the various service beans. + + + + + + This bean defines base properties common to the service beans + + ... + + + + ... + + + + ... + \ No newline at end of file diff --git a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseIdInsteadOfName.xml b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseIdInsteadOfName.xml index af75a2d37dd..f6121793781 100644 --- a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseIdInsteadOfName.xml +++ b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseIdInsteadOfName.xml @@ -1,16 +1,16 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseLocalRef.xml b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseLocalRef.xml index b2dcdea2119..5b6256ee52c 100644 --- a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseLocalRef.xml +++ b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseLocalRef.xml @@ -1,17 +1,17 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseSetterInjection.java b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseSetterInjection.java index d5cf0de1ea6..784b8ff9262 100644 --- a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseSetterInjection.java +++ b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseSetterInjection.java @@ -1,22 +1,22 @@ -// Class for bean 'chart1' -public class WrongChartMaker { - private AxisRenderer axisRenderer = new DefaultAxisRenderer(); - private TrendRenderer trendRenderer = new DefaultTrendRenderer(); - - public WrongChartMaker() {} - - // Each combination of the optional parameters must be represented by a constructor. - public WrongChartMaker(AxisRenderer customAxisRenderer) { - this.axisRenderer = customAxisRenderer; - } - - public WrongChartMaker(TrendRenderer customTrendRenderer) { - this.trendRenderer = customTrendRenderer; - } - - public WrongChartMaker(AxisRenderer customAxisRenderer, - TrendRenderer customTrendRenderer) { - this.axisRenderer = customAxisRenderer; - this.trendRenderer = customTrendRenderer; - } +// Class for bean 'chart1' +public class WrongChartMaker { + private AxisRenderer axisRenderer = new DefaultAxisRenderer(); + private TrendRenderer trendRenderer = new DefaultTrendRenderer(); + + public WrongChartMaker() {} + + // Each combination of the optional parameters must be represented by a constructor. + public WrongChartMaker(AxisRenderer customAxisRenderer) { + this.axisRenderer = customAxisRenderer; + } + + public WrongChartMaker(TrendRenderer customTrendRenderer) { + this.trendRenderer = customTrendRenderer; + } + + public WrongChartMaker(AxisRenderer customAxisRenderer, + TrendRenderer customTrendRenderer) { + this.axisRenderer = customAxisRenderer; + this.trendRenderer = customTrendRenderer; + } } \ No newline at end of file diff --git a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseShortcutForms.xml b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseShortcutForms.xml index 703e67ffe93..0f6afa629f6 100644 --- a/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseShortcutForms.xml +++ b/java/ql/src/Frameworks/Spring/Violations of Best Practice/UseShortcutForms.xml @@ -1,38 +1,38 @@ - - - - main_service_registry - - - Top-level registry for services - - - - - - orderService - - com.foo.bar.OrderService - - - - billingService - - com.foo.bar.BillingService - - - - - - - - - - - - - - - - - + + + + main_service_registry + + + Top-level registry for services + + + + + + orderService + + com.foo.bar.OrderService + + + + billingService + + com.foo.bar.BillingService + + + + + + + + + + + + + + + + + diff --git a/java/ql/src/Frameworks/Spring/XML Configuration Errors/MissingSetters.java b/java/ql/src/Frameworks/Spring/XML Configuration Errors/MissingSetters.java index 6a310cfb758..9541f489ea6 100644 --- a/java/ql/src/Frameworks/Spring/XML Configuration Errors/MissingSetters.java +++ b/java/ql/src/Frameworks/Spring/XML Configuration Errors/MissingSetters.java @@ -1,9 +1,9 @@ -// bean class -public class ContentService { - private TransactionHelper helper; - - // This method does not match the property in the bean file. - public void setHelper(TransactionHelper helper) { - this.helper = helper; - } -} +// bean class +public class ContentService { + private TransactionHelper helper; + + // This method does not match the property in the bean file. + public void setHelper(TransactionHelper helper) { + this.helper = helper; + } +} diff --git a/java/ql/src/Frameworks/Spring/XML Configuration Errors/MissingSetters.xml b/java/ql/src/Frameworks/Spring/XML Configuration Errors/MissingSetters.xml index 9a4ac59115c..42a6b51ca02 100644 --- a/java/ql/src/Frameworks/Spring/XML Configuration Errors/MissingSetters.xml +++ b/java/ql/src/Frameworks/Spring/XML Configuration Errors/MissingSetters.xml @@ -1,7 +1,7 @@ - - - - - - + + + + + + diff --git a/java/ql/src/Likely Bugs/Arithmetic/BadAbsOfRandom.java b/java/ql/src/Likely Bugs/Arithmetic/BadAbsOfRandom.java index 96ab5134a36..ea5aa657ba0 100644 --- a/java/ql/src/Likely Bugs/Arithmetic/BadAbsOfRandom.java +++ b/java/ql/src/Likely Bugs/Arithmetic/BadAbsOfRandom.java @@ -1,17 +1,17 @@ -public static void main(String args[]) { - Random r = new Random(); - - // BAD: 'mayBeNegativeInt' is negative if - // 'nextInt()' returns 'Integer.MIN_VALUE'. - int mayBeNegativeInt = Math.abs(r.nextInt()); - - // GOOD: 'nonNegativeInt' is always a value between 0 (inclusive) - // and Integer.MAX_VALUE (exclusive). - int nonNegativeInt = r.nextInt(Integer.MAX_VALUE); - - // GOOD: When 'nextInt' returns a negative number increment the returned value. - int nextInt = r.nextInt(); - if(nextInt < 0) - nextInt++; - int nonNegativeInt = Math.abs(nextInt); -} +public static void main(String args[]) { + Random r = new Random(); + + // BAD: 'mayBeNegativeInt' is negative if + // 'nextInt()' returns 'Integer.MIN_VALUE'. + int mayBeNegativeInt = Math.abs(r.nextInt()); + + // GOOD: 'nonNegativeInt' is always a value between 0 (inclusive) + // and Integer.MAX_VALUE (exclusive). + int nonNegativeInt = r.nextInt(Integer.MAX_VALUE); + + // GOOD: When 'nextInt' returns a negative number increment the returned value. + int nextInt = r.nextInt(); + if(nextInt < 0) + nextInt++; + int nonNegativeInt = Math.abs(nextInt); +} diff --git a/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.java b/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.java index 63eaedb7717..bb1886a80fe 100644 --- a/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.java +++ b/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.java @@ -1,12 +1,12 @@ -public static void main(String args[]) { - // BAD: A new 'Random' object is created every time - // a pseudo-random integer is required. - int notReallyRandom = new Random().nextInt(); - int notReallyRandom2 = new Random().nextInt(); - - // GOOD: The same 'Random' object is used to generate - // two pseudo-random integers. - Random r = new Random(); - int random1 = r.nextInt(); - int random2 = r.nextInt(); +public static void main(String args[]) { + // BAD: A new 'Random' object is created every time + // a pseudo-random integer is required. + int notReallyRandom = new Random().nextInt(); + int notReallyRandom2 = new Random().nextInt(); + + // GOOD: The same 'Random' object is used to generate + // two pseudo-random integers. + Random r = new Random(); + int random1 = r.nextInt(); + int random2 = r.nextInt(); } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/Concurrency/NonSynchronizedOverride.ql b/java/ql/src/Likely Bugs/Concurrency/NonSynchronizedOverride.ql index ffbe8f34429..eca0dc5f041 100644 --- a/java/ql/src/Likely Bugs/Concurrency/NonSynchronizedOverride.ql +++ b/java/ql/src/Likely Bugs/Concurrency/NonSynchronizedOverride.ql @@ -3,7 +3,7 @@ * @description If a synchronized method is overridden in a subclass, and the overriding method is * not synchronized, the thread-safety of the subclass may be broken. * @kind problem - * @problem.severity error + * @problem.severity warning * @precision very-high * @id java/non-sync-override * @tags reliability diff --git a/java/ql/src/Likely Bugs/Finalization/NullifiedSuperFinalize.java b/java/ql/src/Likely Bugs/Finalization/NullifiedSuperFinalize.java index ddd6d5c7f4f..811e3cdcac6 100644 --- a/java/ql/src/Likely Bugs/Finalization/NullifiedSuperFinalize.java +++ b/java/ql/src/Likely Bugs/Finalization/NullifiedSuperFinalize.java @@ -1,30 +1,30 @@ -class LocalCache { - private Collection localResources; - - //... - - protected void finalize() throws Throwable { - for (NativeResource r : localResources) { - r.dispose(); - } - }; -} - -class WrongCache extends LocalCache { - //... - @Override - protected void finalize() throws Throwable { - // BAD: Empty 'finalize', which does not call 'super.finalize'. - // Native resources in LocalCache are not disposed of. - } -} - -class RightCache extends LocalCache { - //... - @Override - protected void finalize() throws Throwable { - // GOOD: 'finalize' calls 'super.finalize'. - // Native resources in LocalCache are disposed of. - super.finalize(); - } +class LocalCache { + private Collection localResources; + + //... + + protected void finalize() throws Throwable { + for (NativeResource r : localResources) { + r.dispose(); + } + }; +} + +class WrongCache extends LocalCache { + //... + @Override + protected void finalize() throws Throwable { + // BAD: Empty 'finalize', which does not call 'super.finalize'. + // Native resources in LocalCache are not disposed of. + } +} + +class RightCache extends LocalCache { + //... + @Override + protected void finalize() throws Throwable { + // GOOD: 'finalize' calls 'super.finalize'. + // Native resources in LocalCache are disposed of. + super.finalize(); + } } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/Frameworks/JUnit/BadSuiteMethod.java b/java/ql/src/Likely Bugs/Frameworks/JUnit/BadSuiteMethod.java index 2cc578bfff7..9b17c5faf0c 100644 --- a/java/ql/src/Likely Bugs/Frameworks/JUnit/BadSuiteMethod.java +++ b/java/ql/src/Likely Bugs/Frameworks/JUnit/BadSuiteMethod.java @@ -1,21 +1,21 @@ -public class BadSuiteMethod extends TestCase { - // BAD: JUnit 3.8 does not detect the following method as a 'suite' method. - // The method should be public, static, and return 'junit.framework.Test' - // or one of its subtypes. - static Test suite() { - TestSuite suite = new TestSuite(); - suite.addTest(new MyTests("testEquals")); - suite.addTest(new MyTests("testNotEquals")); - return suite; - } -} - -public class CorrectSuiteMethod extends TestCase { - // GOOD: JUnit 3.8 correctly detects the following method as a 'suite' method. - public static Test suite() { - TestSuite suite = new TestSuite(); - suite.addTest(new MyTests("testEquals")); - suite.addTest(new MyTests("testNotEquals")); - return suite; - } +public class BadSuiteMethod extends TestCase { + // BAD: JUnit 3.8 does not detect the following method as a 'suite' method. + // The method should be public, static, and return 'junit.framework.Test' + // or one of its subtypes. + static Test suite() { + TestSuite suite = new TestSuite(); + suite.addTest(new MyTests("testEquals")); + suite.addTest(new MyTests("testNotEquals")); + return suite; + } +} + +public class CorrectSuiteMethod extends TestCase { + // GOOD: JUnit 3.8 correctly detects the following method as a 'suite' method. + public static Test suite() { + TestSuite suite = new TestSuite(); + suite.addTest(new MyTests("testEquals")); + suite.addTest(new MyTests("testNotEquals")); + return suite; + } } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/Frameworks/JUnit/TearDownNoSuper.java b/java/ql/src/Likely Bugs/Frameworks/JUnit/TearDownNoSuper.java index d05d4f16326..2a7ebea4d78 100644 --- a/java/ql/src/Likely Bugs/Frameworks/JUnit/TearDownNoSuper.java +++ b/java/ql/src/Likely Bugs/Frameworks/JUnit/TearDownNoSuper.java @@ -1,65 +1,65 @@ -// Abstract class that initializes then shuts down the -// framework after each set of tests -abstract class FrameworkTestCase extends TestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - Framework.init(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - Framework.shutdown(); - } -} - -// The following classes extend 'FrameworkTestCase' to reuse the -// 'setUp' and 'tearDown' methods of the framework. - -public class TearDownNoSuper extends FrameworkTestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - public void testFramework() { - //... - } - - public void testFramework2() { - //... - } - - @Override - protected void tearDown() throws Exception { - // BAD: Does not call 'super.tearDown'. May cause later tests to fail - // when they try to re-initialize an already initialized framework. - // Even if the framework allows re-initialization, it may maintain the - // internal state, which could affect the results of succeeding tests. - System.out.println("Tests complete"); - } -} - -public class TearDownSuper extends FrameworkTestCase { - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - public void testFramework() { - //... - } - - public void testFramework2() { - //... - } - - @Override - protected void tearDown() throws Exception { - // GOOD: Correctly calls 'super.tearDown' to shut down the - // framework. - System.out.println("Tests complete"); - super.tearDown(); - } +// Abstract class that initializes then shuts down the +// framework after each set of tests +abstract class FrameworkTestCase extends TestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + Framework.init(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + Framework.shutdown(); + } +} + +// The following classes extend 'FrameworkTestCase' to reuse the +// 'setUp' and 'tearDown' methods of the framework. + +public class TearDownNoSuper extends FrameworkTestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testFramework() { + //... + } + + public void testFramework2() { + //... + } + + @Override + protected void tearDown() throws Exception { + // BAD: Does not call 'super.tearDown'. May cause later tests to fail + // when they try to re-initialize an already initialized framework. + // Even if the framework allows re-initialization, it may maintain the + // internal state, which could affect the results of succeeding tests. + System.out.println("Tests complete"); + } +} + +public class TearDownSuper extends FrameworkTestCase { + @Override + protected void setUp() throws Exception { + super.setUp(); + } + + public void testFramework() { + //... + } + + public void testFramework2() { + //... + } + + @Override + protected void tearDown() throws Exception { + // GOOD: Correctly calls 'super.tearDown' to shut down the + // framework. + System.out.println("Tests complete"); + super.tearDown(); + } } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/Frameworks/JUnit/TestCaseNoTests.java b/java/ql/src/Likely Bugs/Frameworks/JUnit/TestCaseNoTests.java index d9ea2cb651d..9c6b6f403de 100644 --- a/java/ql/src/Likely Bugs/Frameworks/JUnit/TestCaseNoTests.java +++ b/java/ql/src/Likely Bugs/Frameworks/JUnit/TestCaseNoTests.java @@ -1,28 +1,28 @@ -// BAD: This test case class does not have any valid JUnit 3.8 test methods. -public class TestCaseNoTests38 extends TestCase { - // This is not a test case because it does not start with 'test'. - public void simpleTest() { - //... - } - - // This is not a test case because it takes two parameters. - public void testNotEquals(int i, int j) { - assertEquals(i != j, true); - } - - // This is recognized as a test, but causes JUnit to fail - // when run because it is not public. - void testEquals() { - //... - } -} - -// GOOD: This test case class correctly declares test methods. -public class MyTests extends TestCase { - public void testEquals() { - assertEquals(1, 1); - } - public void testNotEquals() { - assertFalse(1 == 2); - } +// BAD: This test case class does not have any valid JUnit 3.8 test methods. +public class TestCaseNoTests38 extends TestCase { + // This is not a test case because it does not start with 'test'. + public void simpleTest() { + //... + } + + // This is not a test case because it takes two parameters. + public void testNotEquals(int i, int j) { + assertEquals(i != j, true); + } + + // This is recognized as a test, but causes JUnit to fail + // when run because it is not public. + void testEquals() { + //... + } +} + +// GOOD: This test case class correctly declares test methods. +public class MyTests extends TestCase { + public void testEquals() { + assertEquals(1, 1); + } + public void testNotEquals() { + assertFalse(1 == 2); + } } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/I18N/MissingLocaleArgument.java b/java/ql/src/Likely Bugs/I18N/MissingLocaleArgument.java index 741bc708905..382c80c209a 100644 --- a/java/ql/src/Likely Bugs/I18N/MissingLocaleArgument.java +++ b/java/ql/src/Likely Bugs/I18N/MissingLocaleArgument.java @@ -1,14 +1,14 @@ -public static void main(String args[]) { - String phrase = "I miss my home in Mississippi."; - - // AVOID: Calling 'toLowerCase()' or 'toUpperCase()' - // produces different results depending on what the default locale is. - System.out.println(phrase.toUpperCase()); - System.out.println(phrase.toLowerCase()); - - // GOOD: Explicitly setting the locale when calling 'toLowerCase()' or - // 'toUpperCase()' ensures that the resulting string is - // English, regardless of the default locale. - System.out.println(phrase.toLowerCase(Locale.ENGLISH)); - System.out.println(phrase.toUpperCase(Locale.ENGLISH)); +public static void main(String args[]) { + String phrase = "I miss my home in Mississippi."; + + // AVOID: Calling 'toLowerCase()' or 'toUpperCase()' + // produces different results depending on what the default locale is. + System.out.println(phrase.toUpperCase()); + System.out.println(phrase.toLowerCase()); + + // GOOD: Explicitly setting the locale when calling 'toLowerCase()' or + // 'toUpperCase()' ensures that the resulting string is + // English, regardless of the default locale. + System.out.println(phrase.toLowerCase(Locale.ENGLISH)); + System.out.println(phrase.toUpperCase(Locale.ENGLISH)); } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/Resource Leaks/CloseReader.ql b/java/ql/src/Likely Bugs/Resource Leaks/CloseReader.ql index 5da821a7626..1fd9bddc7bf 100644 --- a/java/ql/src/Likely Bugs/Resource Leaks/CloseReader.ql +++ b/java/ql/src/Likely Bugs/Resource Leaks/CloseReader.ql @@ -3,7 +3,7 @@ * @description A resource that is opened for reading but not closed may cause a resource * leak. * @kind problem - * @problem.severity error + * @problem.severity warning * @precision high * @id java/input-resource-leak * @tags efficiency diff --git a/java/ql/src/Likely Bugs/Resource Leaks/CloseSql.ql b/java/ql/src/Likely Bugs/Resource Leaks/CloseSql.ql index d2681cbb6d1..a2803d7525e 100644 --- a/java/ql/src/Likely Bugs/Resource Leaks/CloseSql.ql +++ b/java/ql/src/Likely Bugs/Resource Leaks/CloseSql.ql @@ -2,7 +2,7 @@ * @name Potential database resource leak * @description A database resource that is opened but not closed may cause a resource leak. * @kind problem - * @problem.severity error + * @problem.severity warning * @precision high * @id java/database-resource-leak * @tags correctness diff --git a/java/ql/src/Likely Bugs/Resource Leaks/CloseWriter.ql b/java/ql/src/Likely Bugs/Resource Leaks/CloseWriter.ql index f0ce36cc821..f854c6c7ab6 100644 --- a/java/ql/src/Likely Bugs/Resource Leaks/CloseWriter.ql +++ b/java/ql/src/Likely Bugs/Resource Leaks/CloseWriter.ql @@ -3,7 +3,7 @@ * @description A resource that is opened for writing but not closed may cause a resource * leak. * @kind problem - * @problem.severity error + * @problem.severity warning * @precision high * @id java/output-resource-leak * @tags efficiency diff --git a/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.java b/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.java index 91ee7d116cd..eaf9e459780 100644 --- a/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.java +++ b/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.java @@ -1,11 +1,11 @@ -class WrongNote implements Serializable { - // BAD: serialVersionUID must be static, final, and 'long' - private static final int serialVersionUID = 1; - - //... -} - -class Note implements Serializable { - // GOOD: serialVersionUID is of the correct type - private static final long serialVersionUID = 1L; +class WrongNote implements Serializable { + // BAD: serialVersionUID must be static, final, and 'long' + private static final int serialVersionUID = 1; + + //... +} + +class Note implements Serializable { + // GOOD: serialVersionUID is of the correct type + private static final long serialVersionUID = 1L; } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.java b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.java index 33599f15e25..57fd8a64cc2 100644 --- a/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.java +++ b/java/ql/src/Likely Bugs/Serialization/IncorrectSerializableMethods.java @@ -1,25 +1,25 @@ -class WrongNetRequest implements Serializable { - // BAD: Does not match the exact signature required for a custom - // deserialization protocol. Will not be called during deserialization. - void readObject(ObjectInputStream in) { - //... - } - - // BAD: Does not match the exact signature required for a custom - // serialization protocol. Will not be called during serialization. - protected void writeObject(ObjectOutputStream out) { - //... - } -} - -class NetRequest implements Serializable { - // GOOD: Signature for a custom deserialization implementation. - private void readObject(ObjectInputStream in) { - //... - } - - // GOOD: Signature for a custom serialization implementation. - private void writeObject(ObjectOutputStream out) { - //... - } +class WrongNetRequest implements Serializable { + // BAD: Does not match the exact signature required for a custom + // deserialization protocol. Will not be called during deserialization. + void readObject(ObjectInputStream in) { + //... + } + + // BAD: Does not match the exact signature required for a custom + // serialization protocol. Will not be called during serialization. + protected void writeObject(ObjectOutputStream out) { + //... + } +} + +class NetRequest implements Serializable { + // GOOD: Signature for a custom deserialization implementation. + private void readObject(ObjectInputStream in) { + //... + } + + // GOOD: Signature for a custom serialization implementation. + private void writeObject(ObjectOutputStream out) { + //... + } } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/Serialization/MissingVoidConstructorOnExternalizable.java b/java/ql/src/Likely Bugs/Serialization/MissingVoidConstructorOnExternalizable.java index fc297ce1788..24c8d634d21 100644 --- a/java/ql/src/Likely Bugs/Serialization/MissingVoidConstructorOnExternalizable.java +++ b/java/ql/src/Likely Bugs/Serialization/MissingVoidConstructorOnExternalizable.java @@ -1,37 +1,37 @@ -class WrongMemo implements Externalizable { - private String memo; - - // BAD: No public no-argument constructor is defined. Deserializing this object - // causes an 'InvalidClassException'. - - public WrongMemo(String memo) { - this.memo = memo; - } - - public void writeExternal(ObjectOutput arg0) throws IOException { - //... - } - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - //... - } -} - -class Memo implements Externalizable { - private String memo; - - // GOOD: Declare a public no-argument constructor, which is used by the - // serialization framework when the object is deserialized. - public Memo() { - } - - public Memo(String memo) { - this.memo = memo; - } - - public void writeExternal(ObjectOutput out) throws IOException { - //... - } - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - //... - } +class WrongMemo implements Externalizable { + private String memo; + + // BAD: No public no-argument constructor is defined. Deserializing this object + // causes an 'InvalidClassException'. + + public WrongMemo(String memo) { + this.memo = memo; + } + + public void writeExternal(ObjectOutput arg0) throws IOException { + //... + } + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + //... + } +} + +class Memo implements Externalizable { + private String memo; + + // GOOD: Declare a public no-argument constructor, which is used by the + // serialization framework when the object is deserialized. + public Memo() { + } + + public Memo(String memo) { + this.memo = memo; + } + + public void writeExternal(ObjectOutput out) throws IOException { + //... + } + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + //... + } } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/Serialization/MissingVoidConstructorsOnSerializable.java b/java/ql/src/Likely Bugs/Serialization/MissingVoidConstructorsOnSerializable.java index d9161f38710..fea0087ba4f 100644 --- a/java/ql/src/Likely Bugs/Serialization/MissingVoidConstructorsOnSerializable.java +++ b/java/ql/src/Likely Bugs/Serialization/MissingVoidConstructorsOnSerializable.java @@ -1,42 +1,42 @@ -class WrongItem { - private String name; - - // BAD: This class does not have a no-argument constructor, and throws an - // 'InvalidClassException' at runtime. - - public WrongItem(String name) { - this.name = name; - } -} - -class WrongSubItem extends WrongItem implements Serializable { - public WrongSubItem() { - super(null); - } - - public WrongSubItem(String name) { - super(name); - } -} - -class Item { - private String name; - - // GOOD: This class declares a no-argument constructor, which allows serializable - // subclasses to be deserialized without error. - public Item() {} - - public Item(String name) { - this.name = name; - } -} - -class SubItem extends Item implements Serializable { - public SubItem() { - super(null); - } - - public SubItem(String name) { - super(name); - } +class WrongItem { + private String name; + + // BAD: This class does not have a no-argument constructor, and throws an + // 'InvalidClassException' at runtime. + + public WrongItem(String name) { + this.name = name; + } +} + +class WrongSubItem extends WrongItem implements Serializable { + public WrongSubItem() { + super(null); + } + + public WrongSubItem(String name) { + super(name); + } +} + +class Item { + private String name; + + // GOOD: This class declares a no-argument constructor, which allows serializable + // subclasses to be deserialized without error. + public Item() {} + + public Item(String name) { + this.name = name; + } +} + +class SubItem extends Item implements Serializable { + public SubItem() { + super(null); + } + + public SubItem(String name) { + super(name); + } } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/Serialization/NonSerializableComparator.java b/java/ql/src/Likely Bugs/Serialization/NonSerializableComparator.java index 1617440e762..d2d758bcebc 100644 --- a/java/ql/src/Likely Bugs/Serialization/NonSerializableComparator.java +++ b/java/ql/src/Likely Bugs/Serialization/NonSerializableComparator.java @@ -1,16 +1,16 @@ -// BAD: This is not serializable, and throws a 'java.io.NotSerializableException' -// when used in a serializable sorted collection. -class WrongComparator implements Comparator { - public int compare(String o1, String o2) { - return o1.compareTo(o2); - } -} - -// GOOD: This is serializable, and can be used in collections that are meant to be serialized. -class StringComparator implements Comparator, Serializable { - private static final long serialVersionUID = -5972458403679726498L; - - public int compare(String arg0, String arg1) { - return arg0.compareTo(arg1); - } +// BAD: This is not serializable, and throws a 'java.io.NotSerializableException' +// when used in a serializable sorted collection. +class WrongComparator implements Comparator { + public int compare(String o1, String o2) { + return o1.compareTo(o2); + } +} + +// GOOD: This is serializable, and can be used in collections that are meant to be serialized. +class StringComparator implements Comparator, Serializable { + private static final long serialVersionUID = -5972458403679726498L; + + public int compare(String arg0, String arg1) { + return arg0.compareTo(arg1); + } } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/Serialization/NonSerializableField.java b/java/ql/src/Likely Bugs/Serialization/NonSerializableField.java index 999e0dc207a..10821b8d785 100644 --- a/java/ql/src/Likely Bugs/Serialization/NonSerializableField.java +++ b/java/ql/src/Likely Bugs/Serialization/NonSerializableField.java @@ -1,27 +1,27 @@ -class DerivedFactors { // Class that contains derived values computed from entries in a - private Number efficiency; // performance record - private Number costPerItem; - private Number profitPerItem; - ... -} - -class WrongPerformanceRecord implements Serializable { - private String unitId; - private Number dailyThroughput; - private Number dailyCost; - private DerivedFactors factors; // BAD: 'DerivedFactors' is not serializable - // but is in a serializable class. This - // causes a 'java.io.NotSerializableException' - // when 'WrongPerformanceRecord' is serialized. - ... -} - -class PerformanceRecord implements Serializable { - private String unitId; - private Number dailyThroughput; - private Number dailyCost; - transient private DerivedFactors factors; // GOOD: 'DerivedFactors' is declared - // 'transient' so it does not contribute to the - // serializable state of 'PerformanceRecord'. - ... -} +class DerivedFactors { // Class that contains derived values computed from entries in a + private Number efficiency; // performance record + private Number costPerItem; + private Number profitPerItem; + ... +} + +class WrongPerformanceRecord implements Serializable { + private String unitId; + private Number dailyThroughput; + private Number dailyCost; + private DerivedFactors factors; // BAD: 'DerivedFactors' is not serializable + // but is in a serializable class. This + // causes a 'java.io.NotSerializableException' + // when 'WrongPerformanceRecord' is serialized. + ... +} + +class PerformanceRecord implements Serializable { + private String unitId; + private Number dailyThroughput; + private Number dailyCost; + transient private DerivedFactors factors; // GOOD: 'DerivedFactors' is declared + // 'transient' so it does not contribute to the + // serializable state of 'PerformanceRecord'. + ... +} diff --git a/java/ql/src/Likely Bugs/Serialization/NonSerializableFieldTooGeneral.java b/java/ql/src/Likely Bugs/Serialization/NonSerializableFieldTooGeneral.java index b2d51cf73e8..1a4a5cc04ca 100644 --- a/java/ql/src/Likely Bugs/Serialization/NonSerializableFieldTooGeneral.java +++ b/java/ql/src/Likely Bugs/Serialization/NonSerializableFieldTooGeneral.java @@ -1,29 +1,29 @@ -class WrongPair implements Serializable{ - private final L left; // BAD - private final R right; // BAD: L and R are not guaranteed to be serializable - - public WrongPair(L left, R right){ ... } - - ... -} - -class Pair implements Serializable{ - private final L left; // GOOD: L and R must implement Serializable - private final R right; - - public Pair(L left, R right){ ... } - - ... -} - -class WrongEvent implements Serializable{ - private Object eventData; // BAD: Type is too general. - - public WrongEvent(Object eventData){ ... } -} - -class Event implements Serializable{ - private Serializable eventData; // GOOD: Force the user to supply only serializable data - - public Event(Serializable eventData){ ... } -} +class WrongPair implements Serializable{ + private final L left; // BAD + private final R right; // BAD: L and R are not guaranteed to be serializable + + public WrongPair(L left, R right){ ... } + + ... +} + +class Pair implements Serializable{ + private final L left; // GOOD: L and R must implement Serializable + private final R right; + + public Pair(L left, R right){ ... } + + ... +} + +class WrongEvent implements Serializable{ + private Object eventData; // BAD: Type is too general. + + public WrongEvent(Object eventData){ ... } +} + +class Event implements Serializable{ + private Serializable eventData; // GOOD: Force the user to supply only serializable data + + public Event(Serializable eventData){ ... } +} diff --git a/java/ql/src/Likely Bugs/Serialization/NonSerializableInnerClass.java b/java/ql/src/Likely Bugs/Serialization/NonSerializableInnerClass.java index d2d44110812..e9a66f56a4a 100644 --- a/java/ql/src/Likely Bugs/Serialization/NonSerializableInnerClass.java +++ b/java/ql/src/Likely Bugs/Serialization/NonSerializableInnerClass.java @@ -1,33 +1,33 @@ -class NonSerializableServer { - - // BAD: The following class is serializable, but the enclosing class - // 'NonSerializableServer' is not. Serializing an instance of 'WrongSession' - // causes a 'java.io.NotSerializableException'. - class WrongSession implements Serializable { - private static final long serialVersionUID = 8970783971992397218L; - private int id; - private String user; - - WrongSession(int id, String user) { /*...*/ } - } - - public WrongSession getNewSession(String user) { - return new WrongSession(newId(), user); - } -} - -class Server { - - // GOOD: The following class can be correctly serialized because it is static. - static class Session implements Serializable { - private static final long serialVersionUID = 1065454318648105638L; - private int id; - private String user; - - Session(int id, String user) { /*...*/ } - } - - public Session getNewSession(String user) { - return new Session(newId(), user); - } +class NonSerializableServer { + + // BAD: The following class is serializable, but the enclosing class + // 'NonSerializableServer' is not. Serializing an instance of 'WrongSession' + // causes a 'java.io.NotSerializableException'. + class WrongSession implements Serializable { + private static final long serialVersionUID = 8970783971992397218L; + private int id; + private String user; + + WrongSession(int id, String user) { /*...*/ } + } + + public WrongSession getNewSession(String user) { + return new WrongSession(newId(), user); + } +} + +class Server { + + // GOOD: The following class can be correctly serialized because it is static. + static class Session implements Serializable { + private static final long serialVersionUID = 1065454318648105638L; + private int id; + private String user; + + Session(int id, String user) { /*...*/ } + } + + public Session getNewSession(String user) { + return new Session(newId(), user); + } } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/Serialization/ReadResolveObject.java b/java/ql/src/Likely Bugs/Serialization/ReadResolveObject.java index cba64daf49c..25057e1ecf2 100644 --- a/java/ql/src/Likely Bugs/Serialization/ReadResolveObject.java +++ b/java/ql/src/Likely Bugs/Serialization/ReadResolveObject.java @@ -1,40 +1,40 @@ -class FalseSingleton implements Serializable { - private static final long serialVersionUID = -7480651116825504381L; - private static FalseSingleton instance; - - private FalseSingleton() {} - - public static FalseSingleton getInstance() { - if (instance == null) { - instance = new FalseSingleton(); - } - return instance; - } - - // BAD: Signature of 'readResolve' does not match the exact signature that is expected - // (that is, it does not return 'java.lang.Object'). - public FalseSingleton readResolve() throws ObjectStreamException { - return FalseSingleton.getInstance(); - } -} - -class Singleton implements Serializable { - private static final long serialVersionUID = -7480651116825504381L; - private static Singleton instance; - - private Singleton() {} - - public static Singleton getInstance() { - if (instance == null) { - instance = new Singleton(); - } - return instance; - } - - // GOOD: Signature of 'readResolve' matches the exact signature that is expected. - // It replaces the singleton that is read from a stream with an instance of 'Singleton', - // instead of creating a new singleton. - private Object readResolve() throws ObjectStreamException { - return Singleton.getInstance(); - } +class FalseSingleton implements Serializable { + private static final long serialVersionUID = -7480651116825504381L; + private static FalseSingleton instance; + + private FalseSingleton() {} + + public static FalseSingleton getInstance() { + if (instance == null) { + instance = new FalseSingleton(); + } + return instance; + } + + // BAD: Signature of 'readResolve' does not match the exact signature that is expected + // (that is, it does not return 'java.lang.Object'). + public FalseSingleton readResolve() throws ObjectStreamException { + return FalseSingleton.getInstance(); + } +} + +class Singleton implements Serializable { + private static final long serialVersionUID = -7480651116825504381L; + private static Singleton instance; + + private Singleton() {} + + public static Singleton getInstance() { + if (instance == null) { + instance = new Singleton(); + } + return instance; + } + + // GOOD: Signature of 'readResolve' matches the exact signature that is expected. + // It replaces the singleton that is read from a stream with an instance of 'Singleton', + // instead of creating a new singleton. + private Object readResolve() throws ObjectStreamException { + return Singleton.getInstance(); + } } \ No newline at end of file diff --git a/java/ql/src/Likely Bugs/Serialization/TransientNotSerializable.java b/java/ql/src/Likely Bugs/Serialization/TransientNotSerializable.java index 783ed4f4181..3025f29bd5e 100644 --- a/java/ql/src/Likely Bugs/Serialization/TransientNotSerializable.java +++ b/java/ql/src/Likely Bugs/Serialization/TransientNotSerializable.java @@ -1,12 +1,12 @@ -class State { - // The 'transient' modifier has no effect here because - // the 'State' class does not implement 'Serializable'. - private transient int[] stateData; -} - -class PersistentState implements Serializable { - private int[] stateData; - // The 'transient' modifier indicates that this field is not part of - // the persistent state and should therefore not be serialized. - private transient int[] cachedComputedData; +class State { + // The 'transient' modifier has no effect here because + // the 'State' class does not implement 'Serializable'. + private transient int[] stateData; +} + +class PersistentState implements Serializable { + private int[] stateData; + // The 'transient' modifier indicates that this field is not part of + // the persistent state and should therefore not be serialized. + private transient int[] cachedComputedData; } \ No newline at end of file diff --git a/java/ql/src/Violations of Best Practice/Dead Code/FinalizerNullsFields.java b/java/ql/src/Violations of Best Practice/Dead Code/FinalizerNullsFields.java index d55d76f835f..7213d78104b 100644 --- a/java/ql/src/Violations of Best Practice/Dead Code/FinalizerNullsFields.java +++ b/java/ql/src/Violations of Best Practice/Dead Code/FinalizerNullsFields.java @@ -1,14 +1,14 @@ -class FinalizedClass { - Object o = new Object(); - String s = "abcdefg"; - Integer i = Integer.valueOf(2); - - @Override - protected void finalize() throws Throwable { - super.finalize(); - //No need to nullify fields - this.o = null; - this.s = null; - this.i = null; - } +class FinalizedClass { + Object o = new Object(); + String s = "abcdefg"; + Integer i = Integer.valueOf(2); + + @Override + protected void finalize() throws Throwable { + super.finalize(); + //No need to nullify fields + this.o = null; + this.s = null; + this.i = null; + } } \ No newline at end of file diff --git a/java/ql/src/Violations of Best Practice/Exception Handling/DroppedExceptions-comment.java b/java/ql/src/Violations of Best Practice/Exception Handling/DroppedExceptions-comment.java index a71288df47d..75f45e61ffc 100644 --- a/java/ql/src/Violations of Best Practice/Exception Handling/DroppedExceptions-comment.java +++ b/java/ql/src/Violations of Best Practice/Exception Handling/DroppedExceptions-comment.java @@ -1,9 +1,9 @@ -synchronized void waitIfAutoSyncScheduled() { - try { - while (isAutoSyncScheduled) { - this.wait(1000); - } - } catch (InterruptedException e) { - // Expected exception. The file cannot be synchronized yet. - } +synchronized void waitIfAutoSyncScheduled() { + try { + while (isAutoSyncScheduled) { + this.wait(1000); + } + } catch (InterruptedException e) { + // Expected exception. The file cannot be synchronized yet. + } } \ No newline at end of file diff --git a/java/ql/src/Violations of Best Practice/Exception Handling/DroppedExceptions-good.java b/java/ql/src/Violations of Best Practice/Exception Handling/DroppedExceptions-good.java index 0085f15c2db..4aeb0f464c9 100644 --- a/java/ql/src/Violations of Best Practice/Exception Handling/DroppedExceptions-good.java +++ b/java/ql/src/Violations of Best Practice/Exception Handling/DroppedExceptions-good.java @@ -1,10 +1,10 @@ -// Exception is passed to 'ignore' method with a comment -synchronized void waitIfAutoSyncScheduled() { - try { - while (isAutoSyncScheduled) { - this.wait(1000); - } - } catch (InterruptedException e) { - Exceptions.ignore(e, "Expected exception. The file cannot be synchronized yet."); - } +// Exception is passed to 'ignore' method with a comment +synchronized void waitIfAutoSyncScheduled() { + try { + while (isAutoSyncScheduled) { + this.wait(1000); + } + } catch (InterruptedException e) { + Exceptions.ignore(e, "Expected exception. The file cannot be synchronized yet."); + } } \ No newline at end of file diff --git a/java/ql/src/Violations of Best Practice/Exception Handling/DroppedExceptions-ignore.java b/java/ql/src/Violations of Best Practice/Exception Handling/DroppedExceptions-ignore.java index 6985620e530..266105c45c2 100644 --- a/java/ql/src/Violations of Best Practice/Exception Handling/DroppedExceptions-ignore.java +++ b/java/ql/src/Violations of Best Practice/Exception Handling/DroppedExceptions-ignore.java @@ -1,5 +1,5 @@ -// 'ignore' method. This method does nothing, but can be called -// to document the reason why the exception can be ignored. -public static void ignore(Throwable e, String message) { - +// 'ignore' method. This method does nothing, but can be called +// to document the reason why the exception can be ignored. +public static void ignore(Throwable e, String message) { + } \ No newline at end of file diff --git a/java/ql/src/Violations of Best Practice/Undesirable Calls/CallsToRunFinalizersOnExit.java b/java/ql/src/Violations of Best Practice/Undesirable Calls/CallsToRunFinalizersOnExit.java index 06655aa8c1f..0a7ec51c920 100644 --- a/java/ql/src/Violations of Best Practice/Undesirable Calls/CallsToRunFinalizersOnExit.java +++ b/java/ql/src/Violations of Best Practice/Undesirable Calls/CallsToRunFinalizersOnExit.java @@ -1,8 +1,8 @@ -void main() { - // ... - // BAD: Call to 'runFinalizersOnExit' forces execution of all finalizers on termination of - // the runtime, which can cause live objects to transition to an invalid state. - // Avoid using this method (and finalizers in general). - System.runFinalizersOnExit(true); - // ... +void main() { + // ... + // BAD: Call to 'runFinalizersOnExit' forces execution of all finalizers on termination of + // the runtime, which can cause live objects to transition to an invalid state. + // Avoid using this method (and finalizers in general). + System.runFinalizersOnExit(true); + // ... } \ No newline at end of file diff --git a/java/ql/src/Violations of Best Practice/Undesirable Calls/CallsToStringToString.java b/java/ql/src/Violations of Best Practice/Undesirable Calls/CallsToStringToString.java index 2fb4df11283..476ac9d49f5 100644 --- a/java/ql/src/Violations of Best Practice/Undesirable Calls/CallsToStringToString.java +++ b/java/ql/src/Violations of Best Practice/Undesirable Calls/CallsToStringToString.java @@ -1,9 +1,9 @@ -public static void main(String args[]) { - String name = "John Doe"; - - // BAD: Unnecessary call to 'toString' on 'name' - System.out.println("Hi, my name is " + name.toString()); - - // GOOD: No call to 'toString' on 'name' - System.out.println("Hi, my name is " + name); +public static void main(String args[]) { + String name = "John Doe"; + + // BAD: Unnecessary call to 'toString' on 'name' + System.out.println("Hi, my name is " + name.toString()); + + // GOOD: No call to 'toString' on 'name' + System.out.println("Hi, my name is " + name); } \ No newline at end of file diff --git a/java/ql/src/Violations of Best Practice/Undesirable Calls/DefaultToString.java b/java/ql/src/Violations of Best Practice/Undesirable Calls/DefaultToString.java index 2cff927b157..7363006363c 100644 --- a/java/ql/src/Violations of Best Practice/Undesirable Calls/DefaultToString.java +++ b/java/ql/src/Violations of Best Practice/Undesirable Calls/DefaultToString.java @@ -1,21 +1,21 @@ -// This class does not have a 'toString' method, so 'java.lang.Object.toString' -// is used when the class is converted to a string. -class WrongPerson { - private String name; - private Date birthDate; - - public WrongPerson(String name, Date birthDate) { - this.name =name; - this.birthDate = birthDate; - } -} - -public static void main(String args[]) throws Exception { - DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd"); - WrongPerson wp = new WrongPerson("Robert Van Winkle", dateFormatter.parse("1967-10-31")); - - // BAD: The following statement implicitly calls 'Object.toString', - // which returns something similar to: - // WrongPerson@4383f74d - System.out.println(wp); +// This class does not have a 'toString' method, so 'java.lang.Object.toString' +// is used when the class is converted to a string. +class WrongPerson { + private String name; + private Date birthDate; + + public WrongPerson(String name, Date birthDate) { + this.name =name; + this.birthDate = birthDate; + } +} + +public static void main(String args[]) throws Exception { + DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd"); + WrongPerson wp = new WrongPerson("Robert Van Winkle", dateFormatter.parse("1967-10-31")); + + // BAD: The following statement implicitly calls 'Object.toString', + // which returns something similar to: + // WrongPerson@4383f74d + System.out.println(wp); } \ No newline at end of file diff --git a/java/ql/src/Violations of Best Practice/Undesirable Calls/GarbageCollection.java b/java/ql/src/Violations of Best Practice/Undesirable Calls/GarbageCollection.java index 47c881dbf20..16d0f46fe09 100644 --- a/java/ql/src/Violations of Best Practice/Undesirable Calls/GarbageCollection.java +++ b/java/ql/src/Violations of Best Practice/Undesirable Calls/GarbageCollection.java @@ -1,15 +1,15 @@ -class RequestHandler extends Thread { - private boolean isRunning; - private Connection conn = new Connection(); - - public void run() { - while (isRunning) { - Request req = conn.getRequest(); - // Process the request ... - - System.gc(); // This call may cause a garbage collection after each request. - // This will likely reduce the throughput of the RequestHandler - // because the JVM spends time on unnecessary garbage collection passes. - } - } +class RequestHandler extends Thread { + private boolean isRunning; + private Connection conn = new Connection(); + + public void run() { + while (isRunning) { + Request req = conn.getRequest(); + // Process the request ... + + System.gc(); // This call may cause a garbage collection after each request. + // This will likely reduce the throughput of the RequestHandler + // because the JVM spends time on unnecessary garbage collection passes. + } + } } \ No newline at end of file diff --git a/java/ql/src/Violations of Best Practice/Undesirable Calls/PrintLnArray.java b/java/ql/src/Violations of Best Practice/Undesirable Calls/PrintLnArray.java index 78f1221829a..5ef908a23e8 100644 --- a/java/ql/src/Violations of Best Practice/Undesirable Calls/PrintLnArray.java +++ b/java/ql/src/Violations of Best Practice/Undesirable Calls/PrintLnArray.java @@ -1,24 +1,24 @@ -public static void main(String args[]) { - String[] words = {"Who", "is", "John", "Galt"}; - String[][] wordMatrix = {{"There", "is"}, {"no", "spoon"}}; - - // BAD: This implicitly uses 'Object.toString' to convert the contents - // of 'words[]', and prints out something similar to: - // [Ljava.lang.String;@459189e1 - System.out.println(words); - - // GOOD: 'Arrays.toString' calls 'toString' on - // each of the array's elements. The statement prints out: - // [Who, is, John, Galt] - System.out.println(Arrays.toString(words)); - - // ALMOST RIGHT: This calls 'toString' on each of the multi-dimensional - // array's elements. However, because the elements are arrays, the statement - // prints out something similar to: - // [[Ljava.lang.String;@55f33675, [Ljava.lang.String;@527c6768]] - System.out.println(Arrays.toString(wordMatrix)); - - // GOOD: This properly prints out the contents of the multi-dimensional array: - // [[There, is], [no, spoon]] - System.out.println(Arrays.deepToString(wordMatrix)); +public static void main(String args[]) { + String[] words = {"Who", "is", "John", "Galt"}; + String[][] wordMatrix = {{"There", "is"}, {"no", "spoon"}}; + + // BAD: This implicitly uses 'Object.toString' to convert the contents + // of 'words[]', and prints out something similar to: + // [Ljava.lang.String;@459189e1 + System.out.println(words); + + // GOOD: 'Arrays.toString' calls 'toString' on + // each of the array's elements. The statement prints out: + // [Who, is, John, Galt] + System.out.println(Arrays.toString(words)); + + // ALMOST RIGHT: This calls 'toString' on each of the multi-dimensional + // array's elements. However, because the elements are arrays, the statement + // prints out something similar to: + // [[Ljava.lang.String;@55f33675, [Ljava.lang.String;@527c6768]] + System.out.println(Arrays.toString(wordMatrix)); + + // GOOD: This properly prints out the contents of the multi-dimensional array: + // [[There, is], [no, spoon]] + System.out.println(Arrays.deepToString(wordMatrix)); } \ No newline at end of file diff --git a/java/ql/src/plugin.xml b/java/ql/src/plugin.xml index ff451072779..e129a194b56 100644 --- a/java/ql/src/plugin.xml +++ b/java/ql/src/plugin.xml @@ -1,16 +1,16 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/java/ql/test/library-tests/comments/.gitattributes b/java/ql/test/library-tests/comments/.gitattributes new file mode 100644 index 00000000000..7ed66a396cf --- /dev/null +++ b/java/ql/test/library-tests/comments/.gitattributes @@ -0,0 +1 @@ +TestWindows.java eol=crlf diff --git a/java/ql/test/library-tests/comments/TestWindows.java b/java/ql/test/library-tests/comments/TestWindows.java index cdefc327c5b..2409adeed8f 100644 --- a/java/ql/test/library-tests/comments/TestWindows.java +++ b/java/ql/test/library-tests/comments/TestWindows.java @@ -1,22 +1,22 @@ -/** - * A JavaDoc comment - * with multiple lines. - */ -class TestWindows { - /** A JavaDoc comment with a single line. */ - void m() { - // a single-line comment - // another single-line comment - } - - /* A block comment - * with multiple lines. - */ - - /* A block comment with a single line. */ - - // an end-of-line comment with a spurious trailing comment marker */ - // an end-of-line comment with trailing whitespace - //an end-of-line comment without a leading space - void test() {} // an end-of-line comment with preceding code -} +/** + * A JavaDoc comment + * with multiple lines. + */ +class TestWindows { + /** A JavaDoc comment with a single line. */ + void m() { + // a single-line comment + // another single-line comment + } + + /* A block comment + * with multiple lines. + */ + + /* A block comment with a single line. */ + + // an end-of-line comment with a spurious trailing comment marker */ + // an end-of-line comment with trailing whitespace + //an end-of-line comment without a leading space + void test() {} // an end-of-line comment with preceding code +} diff --git a/java/ql/test/library-tests/successors/CloseReaderTest/CloseReaderTest.java b/java/ql/test/library-tests/successors/CloseReaderTest/CloseReaderTest.java index f466bb26518..ab52205adf2 100644 --- a/java/ql/test/library-tests/successors/CloseReaderTest/CloseReaderTest.java +++ b/java/ql/test/library-tests/successors/CloseReaderTest/CloseReaderTest.java @@ -1,25 +1,25 @@ -package successors; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; - -public class CloseReaderTest { - public static String readPassword(File keyFile) - { - // TODO: use Console.readPassword() when it's available. - System.out.print("Enter password for " + keyFile - + " (password will not be hidden): "); - System.out.flush(); - BufferedReader stdin = new BufferedReader(new InputStreamReader( - System.in)); - try - { - return stdin.readLine(); - } catch (IOException ex) - { - return null; - } - } -} +package successors; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; + +public class CloseReaderTest { + public static String readPassword(File keyFile) + { + // TODO: use Console.readPassword() when it's available. + System.out.print("Enter password for " + keyFile + + " (password will not be hidden): "); + System.out.flush(); + BufferedReader stdin = new BufferedReader(new InputStreamReader( + System.in)); + try + { + return stdin.readLine(); + } catch (IOException ex) + { + return null; + } + } +} diff --git a/java/ql/test/library-tests/successors/LoopVarReadTest/LoopVarReadTest.java b/java/ql/test/library-tests/successors/LoopVarReadTest/LoopVarReadTest.java index 6f8d45e8438..c0a6d9bba4c 100644 --- a/java/ql/test/library-tests/successors/LoopVarReadTest/LoopVarReadTest.java +++ b/java/ql/test/library-tests/successors/LoopVarReadTest/LoopVarReadTest.java @@ -1,16 +1,16 @@ -package successors; - -public class LoopVarReadTest { - public static void testLoop() - { - int x = 2; - for (int y = 0; y < 10; y += x) - { - System.out.println("Foo"); - } - - int q = 10; - - System.out.println("foo"); - } -} +package successors; + +public class LoopVarReadTest { + public static void testLoop() + { + int x = 2; + for (int y = 0; y < 10; y += x) + { + System.out.println("Foo"); + } + + int q = 10; + + System.out.println("foo"); + } +} diff --git a/java/ql/test/library-tests/successors/SaveFileTest/SaveFileTest.java b/java/ql/test/library-tests/successors/SaveFileTest/SaveFileTest.java index 02b4b46cdb2..f07bf930f41 100644 --- a/java/ql/test/library-tests/successors/SaveFileTest/SaveFileTest.java +++ b/java/ql/test/library-tests/successors/SaveFileTest/SaveFileTest.java @@ -1,56 +1,56 @@ -package successors; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - - -public class SaveFileTest { - public void saveFile(String path, String contentType, - long size, InputStream is) throws FileNotFoundException, - IOException - { - - String savePath = path; - if (path.startsWith("/")) - { - savePath = path.substring(1); - } - - // make sure uploads area exists for this weblog - File dirPath = new File("foo"); - File saveFile = new File(dirPath.getAbsolutePath() + File.separator - + savePath); - - byte[] buffer = new byte[8192]; - int bytesRead = 0; - OutputStream bos = null; - try - { - bos = new FileOutputStream(saveFile); - while ((bytesRead = is.read(buffer, 0, 8192)) != -1) - { - bos.write(buffer, 0, bytesRead); - } - - System.out.println("The file has been written to [" - + saveFile.getAbsolutePath() + "]"); - } catch (Exception e) - { - throw new IOException("ERROR uploading file", e); - } finally - { - try - { - bos.flush(); - bos.close(); - } catch (Exception ignored) - { - } - } - - } -} +package successors; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + + +public class SaveFileTest { + public void saveFile(String path, String contentType, + long size, InputStream is) throws FileNotFoundException, + IOException + { + + String savePath = path; + if (path.startsWith("/")) + { + savePath = path.substring(1); + } + + // make sure uploads area exists for this weblog + File dirPath = new File("foo"); + File saveFile = new File(dirPath.getAbsolutePath() + File.separator + + savePath); + + byte[] buffer = new byte[8192]; + int bytesRead = 0; + OutputStream bos = null; + try + { + bos = new FileOutputStream(saveFile); + while ((bytesRead = is.read(buffer, 0, 8192)) != -1) + { + bos.write(buffer, 0, bytesRead); + } + + System.out.println("The file has been written to [" + + saveFile.getAbsolutePath() + "]"); + } catch (Exception e) + { + throw new IOException("ERROR uploading file", e); + } finally + { + try + { + bos.flush(); + bos.close(); + } catch (Exception ignored) + { + } + } + + } +} diff --git a/java/ql/test/library-tests/successors/TestBreak/TestBreak.java b/java/ql/test/library-tests/successors/TestBreak/TestBreak.java index e9bfc8aecf7..c4663bb21f3 100644 --- a/java/ql/test/library-tests/successors/TestBreak/TestBreak.java +++ b/java/ql/test/library-tests/successors/TestBreak/TestBreak.java @@ -1,86 +1,86 @@ -package successors; - -public class TestBreak { - public void f() - { - //loop breaks - a: - for (;;) - { - int x = 1; - x = x + 1; - if (x == 1) - { - break; - } else - { - for (int q : new int[20]) - { - if (q == 1) - { - break; - } else - { - break a; - } - } - } - } - int y = 12; - while (true) - { - if (y == 1) - { - break; - } else - { - do - { - if (y == 2) - { - break; - } - y = y + 2; - } while (y == 1); - y = 12; - } - } - y = 13; - - //switch breaks - int x =12; - switch (x) - { - case 1: - x = x + 1; - y = y + 1; - case 2: - x = x + 2; - y = y + 2; - break; - case 3: - case 4: - x = x + 3; - y = y + 4; - break; - case 5: - case 6: - x = x + 5; - y = y + 6; - default: - x = y; - y = x; - } - - //no default - switch(x) - { - case 1: - x = 1; - break; - case 2: - x = 2; - break; - } - } -} +package successors; + +public class TestBreak { + public void f() + { + //loop breaks + a: + for (;;) + { + int x = 1; + x = x + 1; + if (x == 1) + { + break; + } else + { + for (int q : new int[20]) + { + if (q == 1) + { + break; + } else + { + break a; + } + } + } + } + int y = 12; + while (true) + { + if (y == 1) + { + break; + } else + { + do + { + if (y == 2) + { + break; + } + y = y + 2; + } while (y == 1); + y = 12; + } + } + y = 13; + + //switch breaks + int x =12; + switch (x) + { + case 1: + x = x + 1; + y = y + 1; + case 2: + x = x + 2; + y = y + 2; + break; + case 3: + case 4: + x = x + 3; + y = y + 4; + break; + case 5: + case 6: + x = x + 5; + y = y + 6; + default: + x = y; + y = x; + } + + //no default + switch(x) + { + case 1: + x = 1; + break; + case 2: + x = 2; + break; + } + } +} diff --git a/java/ql/test/library-tests/successors/TestContinue/TestContinue.java b/java/ql/test/library-tests/successors/TestContinue/TestContinue.java index 5a0042b3540..77e94e5c7ec 100644 --- a/java/ql/test/library-tests/successors/TestContinue/TestContinue.java +++ b/java/ql/test/library-tests/successors/TestContinue/TestContinue.java @@ -1,59 +1,59 @@ -package successors; - -public class TestContinue { - public void f() - { - //loop breaks - a: - for (int p = 0; p < 10;) - { - int x = 1; - x = x + 1; - if (x == 1) - { - continue; - } else - { - for (int q : new int[20]) - { - if (q == 1) - { - continue; - } else if (q == 2) - { - continue a; - } - q = 12; - } - } - } - int y = 12; - while (y != 13) - { - if (y == 1) - { - continue; - } else - { - do - { - if (y == 2) - { - continue; - } - y = y + 2; - } while (y == 1); - y = 12; - } - y = 15; - } - y = 13; - while (y != 12) - { - if (y != 6) - continue; - else - break; - } - } -} +package successors; + +public class TestContinue { + public void f() + { + //loop breaks + a: + for (int p = 0; p < 10;) + { + int x = 1; + x = x + 1; + if (x == 1) + { + continue; + } else + { + for (int q : new int[20]) + { + if (q == 1) + { + continue; + } else if (q == 2) + { + continue a; + } + q = 12; + } + } + } + int y = 12; + while (y != 13) + { + if (y == 1) + { + continue; + } else + { + do + { + if (y == 2) + { + continue; + } + y = y + 2; + } while (y == 1); + y = 12; + } + y = 15; + } + y = 13; + while (y != 12) + { + if (y != 6) + continue; + else + break; + } + } +} diff --git a/java/ql/test/library-tests/successors/TestFinally/TestFinally.java b/java/ql/test/library-tests/successors/TestFinally/TestFinally.java index 19f67f64a9a..51398bc7b8a 100644 --- a/java/ql/test/library-tests/successors/TestFinally/TestFinally.java +++ b/java/ql/test/library-tests/successors/TestFinally/TestFinally.java @@ -1,150 +1,150 @@ -package successors; - -public class TestFinally { - public void f() - { - int z = 12; - try - { - try - { - System.out.println("Try1"); - if (z == 1) - { - return; - } - try - { - System.out.println("Try1"); - if (z == 1) - { - return; - } - System.out.println("Try2"); - } catch (Exception ex) - { - System.out.println("Exception"); - if (z == 1) - { - return; - } - } finally - { - System.out.println("Finally"); - if (z == 1) - { - return; - } - System.out.println("Finally2"); - } - System.out.println("Try2"); - } catch (Exception ex) - { - System.out.println("Exception"); - try - { - System.out.println("Try1"); - if (z == 1) - { - return; - } - System.out.println("Try2"); - } catch (Exception ex2) - { - System.out.println("Exception"); - if (z == 1) - { - return; - } - } finally - { - System.out.println("Finally"); - if (z == 1) - { - return; - } - System.out.println("Finally2"); - } - if (z == 1) - { - return; - } - } finally - { - System.out.println("Finally"); - if (z == 1) - { - return; - } - System.out.println("Finally2"); - } - System.out.println("Foo"); - int y = 12 + 3; - System.out.println("Bar"); - y = y + 1; - return; - } catch (Exception e) - { - try - { - System.out.println("Try1"); - if (z == 1) - { - return; - } - System.out.println("Try2"); - } catch (Exception ex) - { - System.out.println("Exception"); - if (z == 1) - { - return; - } - } finally - { - System.out.println("Finally"); - if (z == 1) - { - return; - } - System.out.println("Finally2"); - } - int x = 1; - System.out.println("Error: " + e); - x = x + 1; - } finally - { - int y = 12; - System.out.println("Finally"); - y = y + 1; - } - z = z + 1; - - try - { - System.out.println("Try1"); - if (z == 1) - { - return; - } - System.out.println("Try2"); - } catch (Exception ex) - { - System.out.println("Exception"); - if (z == 1) - { - return; - } - } finally - { - System.out.println("Finally"); - if (z == 1) - { - return; - } - System.out.println("Finally2"); - } - - z = z + 2; - } -} +package successors; + +public class TestFinally { + public void f() + { + int z = 12; + try + { + try + { + System.out.println("Try1"); + if (z == 1) + { + return; + } + try + { + System.out.println("Try1"); + if (z == 1) + { + return; + } + System.out.println("Try2"); + } catch (Exception ex) + { + System.out.println("Exception"); + if (z == 1) + { + return; + } + } finally + { + System.out.println("Finally"); + if (z == 1) + { + return; + } + System.out.println("Finally2"); + } + System.out.println("Try2"); + } catch (Exception ex) + { + System.out.println("Exception"); + try + { + System.out.println("Try1"); + if (z == 1) + { + return; + } + System.out.println("Try2"); + } catch (Exception ex2) + { + System.out.println("Exception"); + if (z == 1) + { + return; + } + } finally + { + System.out.println("Finally"); + if (z == 1) + { + return; + } + System.out.println("Finally2"); + } + if (z == 1) + { + return; + } + } finally + { + System.out.println("Finally"); + if (z == 1) + { + return; + } + System.out.println("Finally2"); + } + System.out.println("Foo"); + int y = 12 + 3; + System.out.println("Bar"); + y = y + 1; + return; + } catch (Exception e) + { + try + { + System.out.println("Try1"); + if (z == 1) + { + return; + } + System.out.println("Try2"); + } catch (Exception ex) + { + System.out.println("Exception"); + if (z == 1) + { + return; + } + } finally + { + System.out.println("Finally"); + if (z == 1) + { + return; + } + System.out.println("Finally2"); + } + int x = 1; + System.out.println("Error: " + e); + x = x + 1; + } finally + { + int y = 12; + System.out.println("Finally"); + y = y + 1; + } + z = z + 1; + + try + { + System.out.println("Try1"); + if (z == 1) + { + return; + } + System.out.println("Try2"); + } catch (Exception ex) + { + System.out.println("Exception"); + if (z == 1) + { + return; + } + } finally + { + System.out.println("Finally"); + if (z == 1) + { + return; + } + System.out.println("Finally2"); + } + + z = z + 2; + } +} diff --git a/java/ql/test/library-tests/successors/TestFinallyBreakContinue/TestFinallyBreakContinue.java b/java/ql/test/library-tests/successors/TestFinallyBreakContinue/TestFinallyBreakContinue.java index 480713f60d0..04b232a4ba3 100644 --- a/java/ql/test/library-tests/successors/TestFinallyBreakContinue/TestFinallyBreakContinue.java +++ b/java/ql/test/library-tests/successors/TestFinallyBreakContinue/TestFinallyBreakContinue.java @@ -1,108 +1,108 @@ -package successors; - -public class TestFinallyBreakContinue { - public void f() - { - int x = 1; - a: - for (;;) - { - try - { - if (x == 1) - { - break; - } else - { - continue; - } - } catch (Exception e) - { - if (x == 1) - { - break; - } else - { - continue; - } - } finally - { - System.out.println("finally"); - } - } - - while (true) - { - try - { - try - { - if (x == 1) - { - break; - } else - { - continue; - } - } catch (Exception e) - { - if (x == 1) - { - break; - } else - { - continue; - } - } finally - { - System.out.println("finally"); - } - } catch (Exception e) - { - System.out.println("Exception"); - } finally - { - System.out.println("finally"); - } - } - - b: - do - { - try - { - for (int i : new int[20]) - { - try - { - if (x == 1) - { - break; - } else - { - continue; - } - } catch (Exception e) - { - if (x == 1) - { - break b; - } else - { - continue b; - } - } finally - { - System.out.println("finally"); - } - } - } catch (Exception e) - { - System.out.println("Exception"); - } finally - { - System.out.println("finally"); - } - } while (true); - } -} +package successors; + +public class TestFinallyBreakContinue { + public void f() + { + int x = 1; + a: + for (;;) + { + try + { + if (x == 1) + { + break; + } else + { + continue; + } + } catch (Exception e) + { + if (x == 1) + { + break; + } else + { + continue; + } + } finally + { + System.out.println("finally"); + } + } + + while (true) + { + try + { + try + { + if (x == 1) + { + break; + } else + { + continue; + } + } catch (Exception e) + { + if (x == 1) + { + break; + } else + { + continue; + } + } finally + { + System.out.println("finally"); + } + } catch (Exception e) + { + System.out.println("Exception"); + } finally + { + System.out.println("finally"); + } + } + + b: + do + { + try + { + for (int i : new int[20]) + { + try + { + if (x == 1) + { + break; + } else + { + continue; + } + } catch (Exception e) + { + if (x == 1) + { + break b; + } else + { + continue b; + } + } finally + { + System.out.println("finally"); + } + } + } catch (Exception e) + { + System.out.println("Exception"); + } finally + { + System.out.println("finally"); + } + } while (true); + } +} diff --git a/java/ql/test/library-tests/successors/TestLoopBranch/TestLoopBranch.java b/java/ql/test/library-tests/successors/TestLoopBranch/TestLoopBranch.java index 60906547952..058a9d40275 100644 --- a/java/ql/test/library-tests/successors/TestLoopBranch/TestLoopBranch.java +++ b/java/ql/test/library-tests/successors/TestLoopBranch/TestLoopBranch.java @@ -1,120 +1,120 @@ -package successors; - -public class TestLoopBranch { - int xx = 12; - int yy = 13; - - public void f() - { - int x = 1; - int y = 2; - System.out.println("foo"); - - do - { - System.out.println("bar"); - System.out.println("foobar"); - } while (x == 2); - - { - System.out.println("shazam"); - System.out.println("boogie"); - } - - while (x == 1) - { - System.out.println("wonderland"); - System.out.println("shodan"); - x = x + 1; - } - - for (int i = 0; i < 10; i++) - { - System.out.println("rapture"); - y = x - 2; - } - - ; - ; - - for (int j : new int[20]) - { - System.out.println("Zero : " + j); - j = j + x; - } - - if (y == -1) - { - System.out.println("i squared"); - } - - if (x == 42) - { - System.out.println("rat"); - x = 6 * 9; - } else - { - System.out.println("arr"); - x = y * x; - return; - } - - switch (x) - { - case 1: - x = x + 1; - y = y + 1; - case 2: - x = x + 2; - y = y + 2; - break; - case 3: - case 4: - x = x + 3; - y = y + 4; - break; - case 5: - case 6: - x = x + 5; - y = y + 6; - default: - x = y; - y = x; - } - - //no default - switch(x) - { - case 1: - x = 1; - break; - case 2: - x = 2; - break; - } - - Comparable b = new Comparable() { - @Override - public int compareTo(String o) - { - return 0; - } - }; - b.compareTo("Foo"); - - x = x + y; - return; - } - - public TestLoopBranch() - { - xx = 33; - yy = 44; - } - - public TestLoopBranch(int i) - { - xx = i; - yy = i; - } +package successors; + +public class TestLoopBranch { + int xx = 12; + int yy = 13; + + public void f() + { + int x = 1; + int y = 2; + System.out.println("foo"); + + do + { + System.out.println("bar"); + System.out.println("foobar"); + } while (x == 2); + + { + System.out.println("shazam"); + System.out.println("boogie"); + } + + while (x == 1) + { + System.out.println("wonderland"); + System.out.println("shodan"); + x = x + 1; + } + + for (int i = 0; i < 10; i++) + { + System.out.println("rapture"); + y = x - 2; + } + + ; + ; + + for (int j : new int[20]) + { + System.out.println("Zero : " + j); + j = j + x; + } + + if (y == -1) + { + System.out.println("i squared"); + } + + if (x == 42) + { + System.out.println("rat"); + x = 6 * 9; + } else + { + System.out.println("arr"); + x = y * x; + return; + } + + switch (x) + { + case 1: + x = x + 1; + y = y + 1; + case 2: + x = x + 2; + y = y + 2; + break; + case 3: + case 4: + x = x + 3; + y = y + 4; + break; + case 5: + case 6: + x = x + 5; + y = y + 6; + default: + x = y; + y = x; + } + + //no default + switch(x) + { + case 1: + x = 1; + break; + case 2: + x = 2; + break; + } + + Comparable b = new Comparable() { + @Override + public int compareTo(String o) + { + return 0; + } + }; + b.compareTo("Foo"); + + x = x + y; + return; + } + + public TestLoopBranch() + { + xx = 33; + yy = 44; + } + + public TestLoopBranch(int i) + { + xx = i; + yy = i; + } } \ No newline at end of file diff --git a/java/ql/test/library-tests/successors/TestThrow/TestThrow.java b/java/ql/test/library-tests/successors/TestThrow/TestThrow.java index 78df2a3595f..58098fc6505 100644 --- a/java/ql/test/library-tests/successors/TestThrow/TestThrow.java +++ b/java/ql/test/library-tests/successors/TestThrow/TestThrow.java @@ -1,135 +1,135 @@ -package successors; - -import java.io.IOException; -import java.security.InvalidParameterException; - -public class TestThrow { - private TestThrow() throws IOException - { - } - - private void thrower() throws InvalidParameterException - { - } - - public void f() throws Exception - { - int z = 0; - try - { - throw new RuntimeException(); - } catch (RuntimeException e) - { - z = 1; - } catch (Exception e) - { - z = 2; - } - - z = -1; - - try - { - if (z == 1) - { - throw new RuntimeException(); - } else if (z == 2) - { - throw new Exception(); - } else if (z == 3) - { - new TestThrow(); - } else - { - thrower(); - } - } catch (RuntimeException e) - { - z = 1; - } finally - { - z = 2; - } - - z = -1; - - try - { - if (z == 1) - { - throw new Exception(); - } - else if (z == 2) - { - new TestThrow(); - } else - { - thrower(); - } - } catch (RuntimeException e) - { - z = 1; - } - - z = -1; - - try - { - if (z == 1) - throw new Exception(); - } finally - { - z = 1; - } - - try - { - try - { - if (z == 1) - { - throw new Exception(); - } else if (z == 2) - { - throw new RuntimeException(); - } else - { - throw new IOException("Foo bar", null); - } - } catch (RuntimeException e) - { - z = 1; - } - try - { - z = -2; - } finally - { - if (z == 1) - { - throw new Exception(); - } else if (z == 2) - { - throw new RuntimeException(); - } else if (z == 3) - { - throw new IOException("Foo bar", null); - } - } - } catch (IOException e) - { - z = 2; - } - finally - { - z = 3; - } - - if (z == 1) - { - throw new Exception(); - } - - z = -1; - } -} +package successors; + +import java.io.IOException; +import java.security.InvalidParameterException; + +public class TestThrow { + private TestThrow() throws IOException + { + } + + private void thrower() throws InvalidParameterException + { + } + + public void f() throws Exception + { + int z = 0; + try + { + throw new RuntimeException(); + } catch (RuntimeException e) + { + z = 1; + } catch (Exception e) + { + z = 2; + } + + z = -1; + + try + { + if (z == 1) + { + throw new RuntimeException(); + } else if (z == 2) + { + throw new Exception(); + } else if (z == 3) + { + new TestThrow(); + } else + { + thrower(); + } + } catch (RuntimeException e) + { + z = 1; + } finally + { + z = 2; + } + + z = -1; + + try + { + if (z == 1) + { + throw new Exception(); + } + else if (z == 2) + { + new TestThrow(); + } else + { + thrower(); + } + } catch (RuntimeException e) + { + z = 1; + } + + z = -1; + + try + { + if (z == 1) + throw new Exception(); + } finally + { + z = 1; + } + + try + { + try + { + if (z == 1) + { + throw new Exception(); + } else if (z == 2) + { + throw new RuntimeException(); + } else + { + throw new IOException("Foo bar", null); + } + } catch (RuntimeException e) + { + z = 1; + } + try + { + z = -2; + } finally + { + if (z == 1) + { + throw new Exception(); + } else if (z == 2) + { + throw new RuntimeException(); + } else if (z == 3) + { + throw new IOException("Foo bar", null); + } + } + } catch (IOException e) + { + z = 2; + } + finally + { + z = 3; + } + + if (z == 1) + { + throw new Exception(); + } + + z = -1; + } +} diff --git a/java/ql/test/library-tests/successors/TestTryCatch/TestTryCatch.java b/java/ql/test/library-tests/successors/TestTryCatch/TestTryCatch.java index 38b320ae8e1..09466051023 100644 --- a/java/ql/test/library-tests/successors/TestTryCatch/TestTryCatch.java +++ b/java/ql/test/library-tests/successors/TestTryCatch/TestTryCatch.java @@ -1,44 +1,44 @@ -package successors; - -public class TestTryCatch { - public void f() - { - try - { - System.out.println("Foo"); - int y = 12 + 3; - System.out.println("Bar"); - y = y + 1; - } catch (Exception e) - { - int x = 1; - System.out.println("Error: " + e); - x = x + 1; - return; - } finally - { - int y = 12; - System.out.println("Finally"); - y = y + 1; - } - int z = 12; - z = z + 1; - - for (int q = 0; q < 10; q++) - { - try - { - System.out.println("Foo"); - int y = 12 + 3; - System.out.println("Bar"); - y = y + 1; - } catch (RuntimeException e) - { - int x = 1; - System.out.println("Error: " + e); - x = x + 1; - } - } - z = z + 2; - } -} +package successors; + +public class TestTryCatch { + public void f() + { + try + { + System.out.println("Foo"); + int y = 12 + 3; + System.out.println("Bar"); + y = y + 1; + } catch (Exception e) + { + int x = 1; + System.out.println("Error: " + e); + x = x + 1; + return; + } finally + { + int y = 12; + System.out.println("Finally"); + y = y + 1; + } + int z = 12; + z = z + 1; + + for (int q = 0; q < 10; q++) + { + try + { + System.out.println("Foo"); + int y = 12 + 3; + System.out.println("Bar"); + y = y + 1; + } catch (RuntimeException e) + { + int x = 1; + System.out.println("Error: " + e); + x = x + 1; + } + } + z = z + 2; + } +} diff --git a/java/ql/test/query-tests/AlertSuppression/.gitattributes b/java/ql/test/query-tests/AlertSuppression/.gitattributes new file mode 100644 index 00000000000..7ed66a396cf --- /dev/null +++ b/java/ql/test/query-tests/AlertSuppression/.gitattributes @@ -0,0 +1 @@ +TestWindows.java eol=crlf diff --git a/java/ql/test/query-tests/AlertSuppression/TestWindows.java b/java/ql/test/query-tests/AlertSuppression/TestWindows.java index da2539a3083..07845e3c0a5 100644 --- a/java/ql/test/query-tests/AlertSuppression/TestWindows.java +++ b/java/ql/test/query-tests/AlertSuppression/TestWindows.java @@ -1,28 +1,28 @@ -class TestWindows {} // lgtm -// lgtm[java/confusing-method-name] -// lgtm[java/confusing-method-name, java/non-short-circuit-evaluation] -// lgtm[@tag:exceptions] -// lgtm[@tag:exceptions,java/confusing-method-name] -// lgtm[@expires:2017-06-11] -// lgtm[java/confusing-method-name] does not seem confusing despite alert by lgtm -// lgtm: blah blah -// lgtm blah blah #falsepositive -//lgtm [java/confusing-method-name] -/* lgtm */ -// lgtm[] -// lgtmfoo -//lgtm -// lgtm -// lgtm [java/confusing-method-name] -// foolgtm[java/confusing-method-name] -// foolgtm -// foo; lgtm -// foo; lgtm[java/confusing-method-name] -// foo lgtm -// foo lgtm[java/confusing-method-name] -// foo lgtm bar -// foo lgtm[java/confusing-method-name] bar -// LGTM! -// LGTM[java/confusing-method-name] -//lgtm[java/confusing-method-name] and lgtm[java/non-short-circuit-evaluation] -//lgtm[java/confusing-method-name]; lgtm +class TestWindows {} // lgtm +// lgtm[java/confusing-method-name] +// lgtm[java/confusing-method-name, java/non-short-circuit-evaluation] +// lgtm[@tag:exceptions] +// lgtm[@tag:exceptions,java/confusing-method-name] +// lgtm[@expires:2017-06-11] +// lgtm[java/confusing-method-name] does not seem confusing despite alert by lgtm +// lgtm: blah blah +// lgtm blah blah #falsepositive +//lgtm [java/confusing-method-name] +/* lgtm */ +// lgtm[] +// lgtmfoo +//lgtm +// lgtm +// lgtm [java/confusing-method-name] +// foolgtm[java/confusing-method-name] +// foolgtm +// foo; lgtm +// foo; lgtm[java/confusing-method-name] +// foo lgtm +// foo lgtm[java/confusing-method-name] +// foo lgtm bar +// foo lgtm[java/confusing-method-name] bar +// LGTM! +// LGTM[java/confusing-method-name] +//lgtm[java/confusing-method-name] and lgtm[java/non-short-circuit-evaluation] +//lgtm[java/confusing-method-name]; lgtm diff --git a/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql b/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql index 9aec09aa6b6..9a1a3e1aa88 100644 --- a/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql +++ b/javascript/ql/src/Security/CWE-352/MissingCsrfMiddleware.ql @@ -38,12 +38,15 @@ predicate hasCookieMiddleware(Express::RouteHandlerExpr expr, Express::RouteHand * // protected from CSRF * }) * ``` - * - * Currently the predicate only detects `csurf`-based protectors. */ DataFlow::CallNode csrfMiddlewareCreation() { - exists (DataFlow::ModuleImportNode mod | result = mod.getACall() | - mod.getPath() = "csurf" + exists (DataFlow::SourceNode callee | result = callee.getACall() | + callee = DataFlow::moduleImport("csurf") + or + callee = DataFlow::moduleImport("lusca") and + exists(result.getOptionArgument(0, "csrf")) + or + callee = DataFlow::moduleMember("lusca", "csrf") ) } diff --git a/javascript/ql/src/plugin.xml b/javascript/ql/src/plugin.xml index 206533511dc..19bcfc22249 100644 --- a/javascript/ql/src/plugin.xml +++ b/javascript/ql/src/plugin.xml @@ -1,16 +1,16 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/javascript/ql/src/semmle/javascript/frameworks/Express.qll b/javascript/ql/src/semmle/javascript/frameworks/Express.qll index 9e9b52d050e..c0163a143fe 100644 --- a/javascript/ql/src/semmle/javascript/frameworks/Express.qll +++ b/javascript/ql/src/semmle/javascript/frameworks/Express.qll @@ -785,7 +785,8 @@ module Express { override MethodCallExpr astNode; ResponseSendFileAsFileSystemAccess() { - asExpr().(MethodCallExpr).calls(any(ResponseExpr res), "sendFile") + exists (string name | name = "sendFile" or name = "sendfile" | + asExpr().(MethodCallExpr).calls(any(ResponseExpr res), name)) } override DataFlow::Node getAPathArgument() { diff --git a/javascript/ql/test/library-tests/Lines/.gitattributes b/javascript/ql/test/library-tests/Lines/.gitattributes index 4d67c9960a4..3ca67868c63 100644 --- a/javascript/ql/test/library-tests/Lines/.gitattributes +++ b/javascript/ql/test/library-tests/Lines/.gitattributes @@ -1,2 +1,2 @@ -# This file intentionally contains a mix of different line endings -tst1.js -text +# This file intentionally contains a mix of different line endings +tst1.js -text diff --git a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath.expected b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath.expected index 5abd47e9abb..418873e5c6f 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath.expected +++ b/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath.expected @@ -25,4 +25,5 @@ | tainted-array-steps.js:15:29:15:43 | parts.join('/') | This path depends on $@. | tainted-array-steps.js:9:24:9:30 | req.url | a user-provided value | | tainted-require.js:7:19:7:37 | req.param("module") | This path depends on $@. | tainted-require.js:7:19:7:37 | req.param("module") | a user-provided value | | tainted-sendFile.js:7:16:7:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:7:16:7:33 | req.param("gimme") | a user-provided value | +| tainted-sendFile.js:9:16:9:33 | req.param("gimme") | This path depends on $@. | tainted-sendFile.js:9:16:9:33 | req.param("gimme") | a user-provided value | | views.js:1:43:1:55 | req.params[0] | This path depends on $@. | views.js:1:43:1:55 | req.params[0] | a user-provided value | diff --git a/javascript/ql/test/query-tests/Security/CWE-022/tainted-sendFile.js b/javascript/ql/test/query-tests/Security/CWE-022/tainted-sendFile.js index be465c8d5ef..e925f6c566b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-022/tainted-sendFile.js +++ b/javascript/ql/test/query-tests/Security/CWE-022/tainted-sendFile.js @@ -5,4 +5,6 @@ var app = express(); app.get('/some/path', function(req, res) { // BAD: sending a file based on un-sanitized query parameters res.sendFile(req.param("gimme")); + // BAD: same as above + res.sendfile(req.param("gimme")); }); diff --git a/javascript/ql/test/query-tests/Security/CWE-352/MissingCsrfMiddleware.expected b/javascript/ql/test/query-tests/Security/CWE-352/MissingCsrfMiddleware.expected index 974dd70fc55..6e063b6454b 100644 --- a/javascript/ql/test/query-tests/Security/CWE-352/MissingCsrfMiddleware.expected +++ b/javascript/ql/test/query-tests/Security/CWE-352/MissingCsrfMiddleware.expected @@ -1,3 +1,5 @@ | MissingCsrfMiddlewareBad.js:7:9:7:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | MissingCsrfMiddlewareBad.js:10:26:11:1 | functio ... es) {\\n} | here | | csurf_api_example.js:39:37:39:50 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | csurf_api_example.js:39:53:41:3 | functio ... e')\\n } | here | | csurf_example.js:18:9:18:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | csurf_example.js:29:40:31:1 | functio ... sed')\\n} | here | +| lusca_example.js:9:9:9:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | lusca_example.js:23:42:25:1 | functio ... sed')\\n} | here | +| lusca_example.js:9:9:9:22 | cookieParser() | This cookie middleware is serving a request handler $@ without CSRF protection. | lusca_example.js:27:40:29:1 | functio ... sed')\\n} | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-352/lusca_example.js b/javascript/ql/test/query-tests/Security/CWE-352/lusca_example.js new file mode 100644 index 00000000000..ee91d060dd1 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-352/lusca_example.js @@ -0,0 +1,29 @@ +var express = require('express') +var cookieParser = require('cookie-parser') +var bodyParser = require('body-parser') + +var parseForm = bodyParser.urlencoded({ extended: false }) +var lusca = require('lusca'); + +var app = express() +app.use(cookieParser()) + +app.post('/process', parseForm, lusca.csrf(), function (req, res) { // OK + res.send('data is being processed') +}) + +app.post('/process', parseForm, lusca({csrf:true}), function (req, res) { // OK + res.send('data is being processed') +}) + +app.post('/process', parseForm, lusca({csrf:{}}), function (req, res) { // OK + res.send('data is being processed') +}) + +app.post('/process', parseForm, lusca(), function (req, res) { // NOT OK - missing csrf option + res.send('data is being processed') +}) + +app.post('/process_unsafe', parseForm, function (req, res) { // NOT OK + res.send('data is being processed') +})