diff --git a/change_notes/2023-08-02-a8-4-13-false-positives.md b/change_notes/2023-08-02-a8-4-13-false-positives.md new file mode 100644 index 0000000000..1effc84cb7 --- /dev/null +++ b/change_notes/2023-08-02-a8-4-13-false-positives.md @@ -0,0 +1,2 @@ + - `A8-4-13` + - Address false positives caused by missing modelling of modifying operations for smart pointers for some standard libraries (such as libstdc++). \ No newline at end of file diff --git a/change_notes/2023-08-02-smart-pointers.md b/change_notes/2023-08-02-smart-pointers.md new file mode 100644 index 0000000000..f26d1ca27c --- /dev/null +++ b/change_notes/2023-08-02-smart-pointers.md @@ -0,0 +1,5 @@ + - `A20-8-1`/`MEM56-CPP` + - Address false negatives caused by lack of modelling of flow through smart pointers. + - Reduce flow paths through standard library headers to simplify results. + - `A18-1-4` + - Address false positives caused by missing modelling of modifying operations for smart pointers for some standard libraries (such as libstdc++). \ No newline at end of file diff --git a/change_notes/2023-08-03-string-replace.md b/change_notes/2023-08-03-string-replace.md new file mode 100644 index 0000000000..58e5800003 --- /dev/null +++ b/change_notes/2023-08-03-string-replace.md @@ -0,0 +1,2 @@ + - `STR51-CPP` + - Address false negatives caused by incomplete modelling of the `std::string::replace()` function. \ No newline at end of file diff --git a/change_notes/2023-08-04-a15-5-1-noexcept.md b/change_notes/2023-08-04-a15-5-1-noexcept.md new file mode 100644 index 0000000000..3f8c43c64d --- /dev/null +++ b/change_notes/2023-08-04-a15-5-1-noexcept.md @@ -0,0 +1,3 @@ + - `A15-5-1` + - Rephrase alert message for `noalert(false)` special functions to clarify that this permits exceptions. + - Additional results for implicit `noexcept(true)` special functions highlighting that the specification should be made explicit. diff --git a/cpp/autosar/src/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.ql b/cpp/autosar/src/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.ql index 5fbd09d522..47a4e86c19 100644 --- a/cpp/autosar/src/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.ql +++ b/cpp/autosar/src/rules/A15-2-2/ConstructorErrorLeavesObjectInInvalidState.ql @@ -78,11 +78,18 @@ class DeleteWrapperFunction extends Function { class ExceptionThrownInConstructor extends ExceptionThrowingExpr { Constructor c; - ExceptionThrownInConstructor() { exists(getAFunctionThrownType(c, this)) } + ExceptionThrownInConstructor() { + exists(getAFunctionThrownType(c, this)) and + // The constructor is within the users source code + exists(c.getFile().getRelativePath()) + } Constructor getConstructor() { result = c } } +/** + * Add the `nodes` predicate to ensure results with an empty path are still reported. + */ query predicate nodes(ExceptionFlowNode node) { any() } from diff --git a/cpp/autosar/src/rules/A15-5-1/SpecialFunctionMissingNoExceptSpecification.ql b/cpp/autosar/src/rules/A15-5-1/SpecialFunctionMissingNoExceptSpecification.ql index ae61049b6f..77fdd88670 100644 --- a/cpp/autosar/src/rules/A15-5-1/SpecialFunctionMissingNoExceptSpecification.ql +++ b/cpp/autosar/src/rules/A15-5-1/SpecialFunctionMissingNoExceptSpecification.ql @@ -22,15 +22,25 @@ import codingstandards.cpp.exceptions.ExceptionSpecifications from SpecialFunction f, string message where not isExcluded(f, Exceptions2Package::specialFunctionMissingNoExceptSpecificationQuery()) and - not isNoExceptTrue(f) and + not isFDENoExceptTrue(f.getDefinition()) and not f.isCompilerGenerated() and not f.isDeleted() and not f.isDefaulted() and ( isNoExceptExplicitlyFalse(f) and - message = f.getQualifiedName() + " should not be noexcept(false)." + message = + "Special function " + f.getQualifiedName() + + " has a noexcept(false) specification that permits exceptions." or + isNoExceptTrue(f) and + message = + f.getQualifiedName() + + " has an implicit noexcept(true) specification but should make that explicit." + or + not isNoExceptTrue(f) and not isNoExceptExplicitlyFalse(f) and - message = f.getQualifiedName() + " is implicitly noexcept(false) and might throw." + message = + "Special function " + f.getQualifiedName() + + " has an implicit noexcept(false) specification that permits exceptions." ) select f, message diff --git a/cpp/autosar/src/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.ql b/cpp/autosar/src/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.ql index 969373d436..639de937f7 100644 --- a/cpp/autosar/src/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.ql +++ b/cpp/autosar/src/rules/A18-1-4/PointerToAnElementOfAnArrayPassedToASmartPointer.ql @@ -46,17 +46,28 @@ class SingleObjectSmartPointerArrayConstructionConfig extends TaintTracking::Con ( sp.getAConstructorCallWithExternalObjectConstruction().getAnArgument() = sink.asExpr() or - sink.asExpr() = - any(FunctionCall fc, MemberFunction mf | - mf = fc.getTarget() and - mf.getDeclaringType() = sp and - mf.getName() = "reset" - | - fc.getArgument(0) - ) + sink.asExpr() = sp.getAResetCall().getArgument(0) ) ) } + + override predicate isAdditionalTaintStep(DataFlow::Node source, DataFlow::Node sink) { + exists(AutosarUniquePointer sp, FunctionCall fc | + fc = sp.getAReleaseCall() and + source.asExpr() = fc.getQualifier() and + sink.asExpr() = fc + ) + } + + override predicate isSanitizerIn(DataFlow::Node node) { + // Exclude flow into header files outside the source archive which are summarized by the + // additional taint steps above. + exists(AutosarUniquePointer sp | + sp.getAReleaseCall().getTarget() = node.asExpr().(ThisExpr).getEnclosingFunction() + | + not exists(node.getLocation().getFile().getRelativePath()) + ) + } } from diff --git a/cpp/autosar/src/rules/A8-4-13/SharedPtrPassedToFunctionWithImproperSemantics.ql b/cpp/autosar/src/rules/A8-4-13/SharedPtrPassedToFunctionWithImproperSemantics.ql index df757685fb..422818f4c9 100644 --- a/cpp/autosar/src/rules/A8-4-13/SharedPtrPassedToFunctionWithImproperSemantics.ql +++ b/cpp/autosar/src/rules/A8-4-13/SharedPtrPassedToFunctionWithImproperSemantics.ql @@ -19,19 +19,15 @@ import cpp import codingstandards.cpp.autosar import codingstandards.cpp.SmartPointers -Expr underlyingObjectAffectingSharedPointerExpr(Function f) { - result = - any(VariableAccess va, FunctionCall fc | - va.getEnclosingFunction() = f and - // strip the type so as to include reference parameter types - va.getType().stripType() instanceof AutosarSharedPointer and - fc.getTarget().getDeclaringType().stripType() instanceof AutosarSharedPointer and - fc.getQualifier() = va and - // include only calls to methods which modify the underlying object - fc.getTarget().hasName(["operator=", "reset", "swap"]) - | - va - ) +VariableAccess underlyingObjectAffectingSharedPointerExpr(Function f) { + exists(FunctionCall fc | + // Find a call in the function + fc.getEnclosingFunction() = f and + // include only calls to methods which modify the underlying object + fc = any(AutosarSharedPointer s).getAModifyingCall() and + // Report the qualifier + fc.getQualifier() = result + ) } predicate flowsToUnderlyingObjectAffectingExpr(Parameter p) { diff --git a/cpp/autosar/test/rules/A1-1-2.3/options.clang b/cpp/autosar/test/rules/A1-1-2.3/options.clang index e69de29bb2..b45da65784 100644 --- a/cpp/autosar/test/rules/A1-1-2.3/options.clang +++ b/cpp/autosar/test/rules/A1-1-2.3/options.clang @@ -0,0 +1 @@ +-w \ No newline at end of file diff --git a/cpp/autosar/test/rules/A12-0-2/test.cpp b/cpp/autosar/test/rules/A12-0-2/test.cpp index 50dfe4a101..6e640e62d4 100644 --- a/cpp/autosar/test/rules/A12-0-2/test.cpp +++ b/cpp/autosar/test/rules/A12-0-2/test.cpp @@ -1,5 +1,5 @@ #include -#include +#include class A { public: diff --git a/cpp/autosar/test/rules/A15-5-1/SpecialFunctionMissingNoExceptSpecification.expected b/cpp/autosar/test/rules/A15-5-1/SpecialFunctionMissingNoExceptSpecification.expected index 9e698e41ae..4c6a3ae4f7 100644 --- a/cpp/autosar/test/rules/A15-5-1/SpecialFunctionMissingNoExceptSpecification.expected +++ b/cpp/autosar/test/rules/A15-5-1/SpecialFunctionMissingNoExceptSpecification.expected @@ -1,11 +1,11 @@ -| test.cpp:5:3:5:9 | ~ClassA | ClassA::~ClassA should not be noexcept(false). | -| test.cpp:9:3:9:9 | ~ClassB | ClassB::~ClassB should not be noexcept(false). | -| test.cpp:38:6:38:20 | operator delete | operator delete is implicitly noexcept(false) and might throw. | -| test.cpp:43:6:43:20 | operator delete | operator delete is implicitly noexcept(false) and might throw. | -| test.cpp:53:11:53:19 | operator= | ClassF::operator= should not be noexcept(false). | -| test.cpp:63:3:63:8 | ClassH | ClassH::ClassH should not be noexcept(false). | -| test.cpp:68:6:68:9 | swap | swap is implicitly noexcept(false) and might throw. | -| test.cpp:72:6:72:9 | swap | swap should not be noexcept(false). | -| test.cpp:77:8:77:11 | swap | ClassI::swap is implicitly noexcept(false) and might throw. | -| test.cpp:82:8:82:11 | swap | ClassJ::swap is implicitly noexcept(false) and might throw. | -| test.cpp:88:6:88:6 | swap | swap is implicitly noexcept(false) and might throw. | +| test.cpp:5:3:5:9 | ~ClassA | Special function ClassA::~ClassA has a noexcept(false) specification that permits exceptions. | +| test.cpp:9:3:9:9 | ~ClassB | Special function ClassB::~ClassB has a noexcept(false) specification that permits exceptions. | +| test.cpp:38:6:38:20 | operator delete | operator delete has an implicit noexcept(true) specification but should make that explicit. | +| test.cpp:43:6:43:20 | operator delete | operator delete has an implicit noexcept(true) specification but should make that explicit. | +| test.cpp:53:11:53:19 | operator= | Special function ClassF::operator= has a noexcept(false) specification that permits exceptions. | +| test.cpp:63:3:63:8 | ClassH | Special function ClassH::ClassH has a noexcept(false) specification that permits exceptions. | +| test.cpp:68:6:68:9 | swap | Special function swap has an implicit noexcept(false) specification that permits exceptions. | +| test.cpp:72:6:72:9 | swap | Special function swap has a noexcept(false) specification that permits exceptions. | +| test.cpp:77:8:77:11 | swap | Special function ClassI::swap has an implicit noexcept(false) specification that permits exceptions. | +| test.cpp:82:8:82:11 | swap | Special function ClassJ::swap has an implicit noexcept(false) specification that permits exceptions. | +| test.cpp:88:6:88:6 | swap | Special function swap has an implicit noexcept(false) specification that permits exceptions. | diff --git a/cpp/autosar/test/rules/A15-5-1/test.cpp b/cpp/autosar/test/rules/A15-5-1/test.cpp index adc45dd36c..353f4f62d7 100644 --- a/cpp/autosar/test/rules/A15-5-1/test.cpp +++ b/cpp/autosar/test/rules/A15-5-1/test.cpp @@ -1,6 +1,6 @@ #include "stddef.h" +#include #include - class ClassA { ~ClassA() noexcept(false) { throw std::exception(); } // NON_COMPLIANT }; @@ -36,12 +36,12 @@ class ClassD { }; void operator delete(void *ptr) { // NON_COMPLIANT - // NOTE: cannot be declared noexcept(false) + // NOTE: defaults to noexcept(true) throw std::exception(); } void operator delete(void *ptr, size_t size) { // NON_COMPLIANT - // NOTE: cannot be declared noexcept(false) + // NOTE: defaults to noexcept(true) throw std::exception(); } diff --git a/cpp/autosar/test/rules/A16-2-2/UnusedIncludeDirectives.expected.clang b/cpp/autosar/test/rules/A16-2-2/UnusedIncludeDirectives.expected.clang new file mode 100644 index 0000000000..153bf8fa0f --- /dev/null +++ b/cpp/autosar/test/rules/A16-2-2/UnusedIncludeDirectives.expected.clang @@ -0,0 +1 @@ +| test.cpp:1:1:1:19 | #include "test.hpp" | Nothing in this file uses anything from "test.hpp" | diff --git a/cpp/autosar/test/rules/A16-2-2/UnusedIncludeDirectives.expected.gcc b/cpp/autosar/test/rules/A16-2-2/UnusedIncludeDirectives.expected.gcc new file mode 100644 index 0000000000..153bf8fa0f --- /dev/null +++ b/cpp/autosar/test/rules/A16-2-2/UnusedIncludeDirectives.expected.gcc @@ -0,0 +1 @@ +| test.cpp:1:1:1:19 | #include "test.hpp" | Nothing in this file uses anything from "test.hpp" | diff --git a/cpp/autosar/test/rules/A16-2-2/UnusedIncludeDirectives.expected.qcc b/cpp/autosar/test/rules/A16-2-2/UnusedIncludeDirectives.expected.qcc new file mode 100644 index 0000000000..153bf8fa0f --- /dev/null +++ b/cpp/autosar/test/rules/A16-2-2/UnusedIncludeDirectives.expected.qcc @@ -0,0 +1 @@ +| test.cpp:1:1:1:19 | #include "test.hpp" | Nothing in this file uses anything from "test.hpp" | diff --git a/cpp/autosar/test/rules/A16-2-2/test.cpp b/cpp/autosar/test/rules/A16-2-2/test.cpp index 50c66461b4..571675ab18 100644 --- a/cpp/autosar/test/rules/A16-2-2/test.cpp +++ b/cpp/autosar/test/rules/A16-2-2/test.cpp @@ -1,5 +1,5 @@ -#include "test.hpp" //NON_COMPLIANT -#include //NON_COMPLIANT +#include "test.hpp" //NON_COMPLIANT +#include //NON_COMPLIANT - redundant but not useless on real compilers #include //COMPLIANT std::vector v; \ No newline at end of file diff --git a/cpp/autosar/test/rules/A18-5-5/test.cpp b/cpp/autosar/test/rules/A18-5-5/test.cpp index 73244c15a6..b125f2201a 100644 --- a/cpp/autosar/test/rules/A18-5-5/test.cpp +++ b/cpp/autosar/test/rules/A18-5-5/test.cpp @@ -11,7 +11,7 @@ void *malloc1(int b) { // NON_COMPLIANT - recursion return malloc1(b - 1); } -void *malloc2(int b) __attribute__((no_caller_saved_registers, __malloc__)); +void *malloc2(int b) __attribute__((__malloc__)); void *malloc2(int b) { // NON_COMPLIANT - execution doesn't depend on b for (int i = 0; i < 10; i++) { diff --git a/cpp/autosar/test/rules/A18-5-6/test.cpp b/cpp/autosar/test/rules/A18-5-6/test.cpp index 576dbc02fa..a9434ed1b5 100644 --- a/cpp/autosar/test/rules/A18-5-6/test.cpp +++ b/cpp/autosar/test/rules/A18-5-6/test.cpp @@ -4,7 +4,7 @@ void *malloc1(int b) __attribute__((malloc)); void *malloc1(int b) { return nullptr; } // NON_COMPLIANT -void *malloc3(int b) __attribute__((no_caller_saved_registers, __malloc__)); +void *malloc3(int b) __attribute__((__malloc__)); void *malloc3(int b) { return nullptr; } // NON_COMPLIANT void h1() {} // NON_COMPLIANT diff --git a/cpp/autosar/test/rules/M18-0-5/test.cpp b/cpp/autosar/test/rules/M18-0-5/test.cpp index 521326bef7..37ea1f6415 100644 --- a/cpp/autosar/test/rules/M18-0-5/test.cpp +++ b/cpp/autosar/test/rules/M18-0-5/test.cpp @@ -1,4 +1,4 @@ -#include +#include void test_unbounded_str_funs() { char str1[] = "Sample string"; diff --git a/cpp/cert/test/rules/EXP62-CPP/test.cpp b/cpp/cert/test/rules/EXP62-CPP/test.cpp index 1f80dc04c2..ebda14e624 100644 --- a/cpp/cert/test/rules/EXP62-CPP/test.cpp +++ b/cpp/cert/test/rules/EXP62-CPP/test.cpp @@ -1,4 +1,4 @@ -#include +#include struct S1 { int i, j, k; diff --git a/cpp/cert/test/rules/OOP57-CPP/test.cpp b/cpp/cert/test/rules/OOP57-CPP/test.cpp index 02059f98cc..430c910985 100644 --- a/cpp/cert/test/rules/OOP57-CPP/test.cpp +++ b/cpp/cert/test/rules/OOP57-CPP/test.cpp @@ -1,4 +1,4 @@ -#include +#include class trivial {}; diff --git a/cpp/common/src/codingstandards/cpp/Concurrency.qll b/cpp/common/src/codingstandards/cpp/Concurrency.qll index 7c92d93752..609cfafc4b 100644 --- a/cpp/common/src/codingstandards/cpp/Concurrency.qll +++ b/cpp/common/src/codingstandards/cpp/Concurrency.qll @@ -114,7 +114,10 @@ class CPPMutexFunctionCall extends MutexFunctionCall { /** * Holds if this `CPPMutexFunctionCall` is a lock. */ - override predicate isLock() { getTarget().getName() = "lock" } + override predicate isLock() { + not isLockingOperationWithinLockingOperation(this) and + getTarget().getName() = "lock" + } /** * Holds if this `CPPMutexFunctionCall` is a speculative lock, defined as calling @@ -172,6 +175,7 @@ class CMutexFunctionCall extends MutexFunctionCall { * Holds if this `CMutexFunctionCall` is a lock. */ override predicate isLock() { + not isLockingOperationWithinLockingOperation(this) and getTarget().getName() = ["mtx_lock", "mtx_timedlock", "mtx_trylock"] } @@ -296,6 +300,16 @@ abstract class LockingOperation extends FunctionCall { * Holds if this is an unlock operation */ abstract predicate isUnlock(); + + /** + * Holds if this locking operation is really a locking operation within a + * designated locking operation. This library assumes the underlying locking + * operations are implemented correctly in that calling a `LockingOperation` + * results in the creation of a singular lock. + */ + predicate isLockingOperationWithinLockingOperation(LockingOperation inner) { + exists(LockingOperation outer | outer.getTarget() = inner.getEnclosingFunction()) + } } /** @@ -317,6 +331,7 @@ class RAIIStyleLock extends LockingOperation { * Holds if this is a lock operation */ override predicate isLock() { + not isLockingOperationWithinLockingOperation(this) and this instanceof ConstructorCall and lock = getArgument(0).getAChild*() and // defer_locks don't cause a lock diff --git a/cpp/common/src/codingstandards/cpp/SmartPointers.qll b/cpp/common/src/codingstandards/cpp/SmartPointers.qll index aa9ea420a3..0f01d886be 100644 --- a/cpp/common/src/codingstandards/cpp/SmartPointers.qll +++ b/cpp/common/src/codingstandards/cpp/SmartPointers.qll @@ -29,6 +29,11 @@ abstract class AutosarSmartPointer extends Class { ) } + FunctionCall getAGetCall() { + result.getTarget().hasName("get") and + result.getQualifier().getType().stripType() = this + } + FunctionCall getAnInitializerExpr() { result = any(FunctionCall fc | @@ -51,10 +56,25 @@ abstract class AutosarSmartPointer extends Class { AutosarSmartPointer ) } + + FunctionCall getAResetCall() { + result.getTarget().hasName("reset") and + result.getQualifier().getType().stripType() = this + } + + FunctionCall getAModifyingCall() { + result.getTarget().hasName(["operator=", "reset", "swap"]) and + result.getQualifier().getType().stripType() = this + } } class AutosarUniquePointer extends AutosarSmartPointer { AutosarUniquePointer() { this.hasQualifiedName("std", "unique_ptr") } + + FunctionCall getAReleaseCall() { + result.getTarget().hasName("release") and + result.getQualifier().getType().stripType() = this + } } class AutosarSharedPointer extends AutosarSmartPointer { diff --git a/cpp/common/src/codingstandards/cpp/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.qll b/cpp/common/src/codingstandards/cpp/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.qll index ced6545e39..30caf12d75 100644 --- a/cpp/common/src/codingstandards/cpp/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.qll +++ b/cpp/common/src/codingstandards/cpp/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.qll @@ -29,6 +29,34 @@ private class PointerToSmartPointerConstructorFlowConfig extends TaintTracking:: cc.getArgument(0) = sink.asExpr() ) } + + override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + // Summarize flow through constructor calls + exists(AutosarSmartPointer sp, ConstructorCall cc | + sp.getAConstructorCall() = cc and + cc = node2.asExpr() and + cc.getArgument(0) = node1.asExpr() + ) + or + // Summarize flow through get() calls + exists(AutosarSmartPointer sp, FunctionCall fc | + sp.getAGetCall() = fc and + fc = node2.asExpr() and + fc.getQualifier() = node1.asExpr() + ) + } + + override predicate isSanitizerIn(DataFlow::Node node) { + // Exclude flow into header files outside the source archive which are summarized by the + // additional taint steps above. + exists(AutosarSmartPointer sp | + sp.getAConstructorCall().getTarget().getAParameter() = node.asParameter() + or + sp.getAGetCall().getTarget().getAParameter() = node.asParameter() + | + not exists(node.getLocation().getFile().getRelativePath()) + ) + } } query predicate problems( diff --git a/cpp/common/src/codingstandards/cpp/rules/preventdeadlockbylockinginpredefinedorder/PreventDeadlockByLockingInPredefinedOrder.qll b/cpp/common/src/codingstandards/cpp/rules/preventdeadlockbylockinginpredefinedorder/PreventDeadlockByLockingInPredefinedOrder.qll index 3767f023a0..db755293c6 100644 --- a/cpp/common/src/codingstandards/cpp/rules/preventdeadlockbylockinginpredefinedorder/PreventDeadlockByLockingInPredefinedOrder.qll +++ b/cpp/common/src/codingstandards/cpp/rules/preventdeadlockbylockinginpredefinedorder/PreventDeadlockByLockingInPredefinedOrder.qll @@ -24,7 +24,11 @@ predicate getAnOrderedLockPair( lock1 = node.coveredByLock() and lock2 = node.coveredByLock() and not lock1 = lock2 and - lock1.getEnclosingFunction() = lock2.getEnclosingFunction() and + exists(Function f | + lock1.getEnclosingFunction() = f and + lock2.getEnclosingFunction() = f and + node.getBasicBlock().getEnclosingFunction() = f + ) and exists(Location l1Loc, Location l2Loc | l1Loc = lock1.getLocation() and l2Loc = lock2.getLocation() diff --git a/cpp/common/src/codingstandards/cpp/standardlibrary/String.qll b/cpp/common/src/codingstandards/cpp/standardlibrary/String.qll index ed6a4fc8b2..f233410b89 100644 --- a/cpp/common/src/codingstandards/cpp/standardlibrary/String.qll +++ b/cpp/common/src/codingstandards/cpp/standardlibrary/String.qll @@ -45,7 +45,8 @@ class StdBasicString extends ClassTemplateInstantiation { Type getConstIteratorType() { exists(TypedefType t | t.getDeclaringType() = this and - t.getName() = "const_iterator" and + // Certain compilers user __const_iterator instead of const_iterator. + t.getName() = ["const_iterator", "__const_iterator"] and result = t ) } diff --git a/cpp/common/test/includes/standard-library/array b/cpp/common/test/includes/standard-library/array index b77ca4ca99..ca4d3291ad 100644 --- a/cpp/common/test/includes/standard-library/array +++ b/cpp/common/test/includes/standard-library/array @@ -1,7 +1,7 @@ #ifndef _GHLIBCPP_ARRAY #define _GHLIBCPP_ARRAY -#include "iterator.h" -#include "string.h" +#include +#include // Note: a few features currently unused by tests are commented out namespace std { diff --git a/cpp/common/test/includes/standard-library/cerrno b/cpp/common/test/includes/standard-library/cerrno index f1957abe6a..679ce128ea 100644 --- a/cpp/common/test/includes/standard-library/cerrno +++ b/cpp/common/test/includes/standard-library/cerrno @@ -1,2 +1 @@ -int __errno; -#define errno __errno \ No newline at end of file +#include \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/cstring.h b/cpp/common/test/includes/standard-library/cstring.h index 8c34428fa8..2f3ffd393e 100644 --- a/cpp/common/test/includes/standard-library/cstring.h +++ b/cpp/common/test/includes/standard-library/cstring.h @@ -1,8 +1,29 @@ #ifndef _GHLIBCPP_CSTRING #define _GHLIBCPP_CSTRING -typedef unsigned long size_t; + +#include + namespace std { -void *memcpy(void *, const void *, size_t); -size_t strlen(const char *); +using ::memcmp; +using ::memcpy; +using ::memmove; +using ::memset; +using ::size_t; +using ::strcat; +using ::strchr; +using ::strcmp; +using ::strcoll; +using ::strcpy; +using ::strcspn; +using ::strlen; +using ::strncat; +using ::strncmp; +using ::strncpy; +using ::strpbrk; +using ::strrchr; +using ::strspn; +using ::strstr; +using ::strtok; +using ::strxfrm; } // namespace std #endif // _GHLIBCPP_CSTRING diff --git a/cpp/common/test/includes/standard-library/deque.h b/cpp/common/test/includes/standard-library/deque.h index aee0573229..00b44b704a 100644 --- a/cpp/common/test/includes/standard-library/deque.h +++ b/cpp/common/test/includes/standard-library/deque.h @@ -1,7 +1,7 @@ #ifndef _GHLIBCPP_DEQUE #define _GHLIBCPP_DEQUE -#include "iterator.h" -#include "string.h" +#include +#include namespace std { template > class deque { diff --git a/cpp/common/test/includes/standard-library/errno.h b/cpp/common/test/includes/standard-library/errno.h index 96195e6e19..be17eeb0b5 100644 --- a/cpp/common/test/includes/standard-library/errno.h +++ b/cpp/common/test/includes/standard-library/errno.h @@ -1,3 +1,5 @@ -namespace std { -typedef int errno_t; -} // namespace std \ No newline at end of file +#ifndef _GHLIBCPP_ERRNO +#define _GHLIBCPP_ERRNO +int __errno; +#define errno __errno +#endif // _GHLIBCPP_ERRNO \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/istream.h b/cpp/common/test/includes/standard-library/istream.h index f1758e6930..f56e67b8c5 100644 --- a/cpp/common/test/includes/standard-library/istream.h +++ b/cpp/common/test/includes/standard-library/istream.h @@ -1,8 +1,8 @@ #ifndef _GHLIBCPP_ISTREAM #define _GHLIBCPP_ISTREAM -#include "ios.h" -#include "string.h" +#include +#include namespace std { template diff --git a/cpp/common/test/includes/standard-library/memory.h b/cpp/common/test/includes/standard-library/memory.h index cf8be3fade..985ee41602 100644 --- a/cpp/common/test/includes/standard-library/memory.h +++ b/cpp/common/test/includes/standard-library/memory.h @@ -1,7 +1,7 @@ #ifndef _GHLIBCPP_MEMORY #define _GHLIBCPP_MEMORY -#include "stddef.h" #include "exception.h" +#include "stddef.h" namespace std { @@ -18,6 +18,7 @@ template struct default_delete { template > class unique_ptr { public: + typedef T *pointer; unique_ptr() {} unique_ptr(T *ptr) {} unique_ptr(const unique_ptr &t) = delete; @@ -27,9 +28,7 @@ class unique_ptr { T *operator->() const noexcept { return ptr; } T *get() const noexcept { return ptr; } T *release() { return ptr; } - void reset() {} - void reset(T *ptr) {} - void reset(T ptr) {} + void reset(pointer __p = pointer()) {} T *get() { return ptr; } unique_ptr &operator=(const unique_ptr &) = delete; unique_ptr &operator=(unique_ptr &&) { return *this; } @@ -58,35 +57,49 @@ template class unique_ptr { pointer get() const noexcept; explicit operator bool() const noexcept; - pointer release() noexcept; + pointer release() noexcept { + pointer __p = get(); + _M_p = pointer(); + return __p; + } void reset(pointer p = pointer()) noexcept; void reset(nullptr_t) noexcept; template void reset(U) = delete; void swap(unique_ptr &u) noexcept; unique_ptr(const unique_ptr &) = delete; unique_ptr &operator=(const unique_ptr &) = delete; + +private: + pointer _M_p; }; template unique_ptr make_unique(Args &&...args); template unique_ptr make_unique(size_t n); -template class shared_ptr { +template class __shared_ptr { +public: + void reset() noexcept; + template void reset(Y *p); + template void reset(Y *p, D d); + template void reset(Y *p, D d, A a); + + long use_count() const noexcept; + T *get() const noexcept; +}; + +template class shared_ptr : public __shared_ptr { public: - shared_ptr() {} - shared_ptr(T *ptr) {} + shared_ptr(); + shared_ptr(T *ptr); shared_ptr(const shared_ptr &r) noexcept; template shared_ptr(const shared_ptr &r) noexcept; shared_ptr(shared_ptr &&r) noexcept; template shared_ptr(shared_ptr &&r) noexcept; shared_ptr(unique_ptr &&t) {} ~shared_ptr() {} - T &operator*() const { return *ptr; } - T *operator->() const noexcept { return ptr; } - void reset() {} - void reset(T *pt) {} - void reset(T pt) {} - long use_count() const noexcept { return 0; } - T *get() { return ptr; } + T &operator*() const noexcept; + T *operator->() const noexcept; + shared_ptr &operator=(const shared_ptr &) {} shared_ptr &operator=(shared_ptr &&) { return *this; } template shared_ptr &operator=(shared_ptr &&) { diff --git a/cpp/common/test/includes/standard-library/mutex.h b/cpp/common/test/includes/standard-library/mutex.h index 4f16824861..4c49819ddd 100644 --- a/cpp/common/test/includes/standard-library/mutex.h +++ b/cpp/common/test/includes/standard-library/mutex.h @@ -23,7 +23,7 @@ constexpr try_to_lock_t try_to_lock{}; class mutex { public: constexpr mutex() noexcept; - ~mutex(); + ~mutex() = default; mutex(const mutex &) = delete; mutex &operator=(const mutex &) = delete; void lock(); @@ -62,15 +62,19 @@ template void swap(unique_lock &x, unique_lock &y) noexcept; template -void lock(_Lock0 &_Lk0, _Lock1 &_Lk1, _LockN &..._LkN) { } +void lock(_Lock0 &_Lk0, _Lock1 &_Lk1, _LockN &..._LkN) {} template class lock_guard { public: typedef Mutex mutex_type; - explicit lock_guard(mutex_type &__m); + explicit lock_guard(mutex_type &__m) : _m(__m) { _m.lock(); } lock_guard(const lock_guard &) = delete; lock_guard &operator=(const lock_guard &) = delete; + ~lock_guard() { _m.unlock(); } + +private: + mutex_type &_m; }; } // namespace std diff --git a/cpp/common/test/includes/standard-library/ostream.h b/cpp/common/test/includes/standard-library/ostream.h index bde2b7a53f..9f2c6d9069 100644 --- a/cpp/common/test/includes/standard-library/ostream.h +++ b/cpp/common/test/includes/standard-library/ostream.h @@ -1,7 +1,7 @@ #ifndef _GHLIBCPP_OSTREAM #define _GHLIBCPP_OSTREAM -#include "string.h" #include +#include namespace std { template diff --git a/cpp/common/test/includes/standard-library/random.h b/cpp/common/test/includes/standard-library/random.h index e3f3dcab0a..1a2b341226 100644 --- a/cpp/common/test/includes/standard-library/random.h +++ b/cpp/common/test/includes/standard-library/random.h @@ -2,7 +2,7 @@ #define _GHLIBCPP_RANDOM #include "cstdint.h" #include "stddef.h" -#include "string.h" +#include namespace std { template diff --git a/cpp/common/test/includes/standard-library/stdexcept.h b/cpp/common/test/includes/standard-library/stdexcept.h index fd9f7f9e6d..cb9af14db2 100644 --- a/cpp/common/test/includes/standard-library/stdexcept.h +++ b/cpp/common/test/includes/standard-library/stdexcept.h @@ -1,7 +1,7 @@ #ifndef _GHLIBCPP_STDEXCEPT #define _GHLIBCPP_STDEXCEPT -#include "exception.h" -#include "string.h" +#include +#include namespace std { class logic_error : public exception { diff --git a/cpp/common/test/includes/standard-library/string b/cpp/common/test/includes/standard-library/string index de6c8e145a..ca267f6191 100644 --- a/cpp/common/test/includes/standard-library/string +++ b/cpp/common/test/includes/standard-library/string @@ -1 +1,251 @@ -#include \ No newline at end of file +#ifndef _GHLIBCPP_STRING +#define _GHLIBCPP_STRING +#include "initializer_list" +#include "iosfwd.h" +#include "iterator.h" +#include "stddef.h" + +namespace std { +template struct char_traits; + +template class allocator { +public: + allocator() throw(); + typedef size_t size_type; +}; + +template , + class Allocator = allocator> +class basic_string { +public: + using value_type = charT; + using reference = value_type &; + using const_reference = const value_type &; + typedef typename Allocator::size_type size_type; + static const size_type npos = -1; + + basic_string() : basic_string(Allocator()) {} + explicit basic_string(const Allocator &a); + basic_string(const basic_string &str); + basic_string(basic_string &&str) noexcept; + basic_string(const charT *s, size_type n, const Allocator &a = Allocator()); + basic_string(const charT *s, const Allocator &a = Allocator()); + basic_string(size_type n, charT c, const Allocator &a = Allocator()); + template + basic_string(InputIterator begin, InputIterator end, + const Allocator &a = Allocator()); + + ~basic_string(); + basic_string &operator=(const basic_string &str); + basic_string &operator=(basic_string &&str) noexcept; + basic_string &operator=(const charT *s); + basic_string &operator=(charT c); + basic_string &operator=(initializer_list); + + const charT *c_str() const; + charT *data() noexcept; + size_type size() const noexcept; + size_type length() const noexcept; + + typedef __iterator iterator; + typedef __iterator __const_iterator; + typedef __const_iterator const_iterator; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + const_iterator cbegin() const; + const_iterator cend() const; + + const charT &front() const; + charT &front(); + const charT &back() const; + charT &back(); + + const_reference operator[](size_type pos) const; + reference operator[](size_type pos); + const_reference at(size_type n) const; + reference at(size_type n); + basic_string &operator+=(const basic_string &str); + basic_string &operator+=(const charT *s); + basic_string &operator+=(charT c); + basic_string &operator+=(initializer_list); + basic_string &append(const basic_string &str); + basic_string &append(const basic_string &str, size_type pos, + size_type n = npos); + basic_string &append(const charT *s, size_type n); + basic_string &append(const charT *s); + basic_string &append(size_type n, charT c); + template + basic_string &append(InputIterator first, InputIterator last); + basic_string &append(initializer_list); + void push_back(charT c); + basic_string &assign(const basic_string &str); + basic_string &assign(basic_string &&str) noexcept; + basic_string &assign(const basic_string &str, size_type pos, + size_type n = npos); + basic_string &assign(const charT *s, size_type n); + basic_string &assign(const charT *s); + basic_string &assign(size_type n, charT c); + template + basic_string &assign(InputIterator first, InputIterator last); + basic_string &assign(initializer_list); + basic_string &insert(size_type pos1, const basic_string &str); + basic_string &insert(size_type pos1, const basic_string &str, size_type pos2, + size_type n = npos); + basic_string &insert(size_type pos, const charT *s, size_type n); + basic_string &insert(size_type pos, const charT *s); + basic_string &insert(size_type pos, size_type n, charT c); + iterator insert(const_iterator p, charT c); + iterator insert(const_iterator p, size_type n, charT c); + template + iterator insert(const_iterator p, InputIterator first, InputIterator last); + iterator insert(const_iterator p, initializer_list); + basic_string &erase(size_type pos = 0, size_type n = npos); + iterator erase(const_iterator p); + iterator erase(const_iterator first, const_iterator last); + basic_string &replace(size_type pos1, size_type n1, const basic_string &str); + basic_string &replace(size_type pos1, size_type n1, const basic_string &str, + size_type pos2, size_type n2 = npos); + basic_string &replace(size_type pos, size_type n1, const charT *s, + size_type n2); + basic_string &replace(size_type pos, size_type n1, const charT *s); + basic_string &replace(size_type pos, size_type n1, size_type n2, charT c); + basic_string &replace(__const_iterator i1, __const_iterator i2, + const basic_string &str); + basic_string &replace(__const_iterator i1, __const_iterator i2, const charT *s, + size_type n); + basic_string &replace(__const_iterator i1, __const_iterator i2, const charT *s); + basic_string &replace(__const_iterator i1, __const_iterator i2, size_type n, + charT c); + template + basic_string &replace(__const_iterator i1, __const_iterator i2, InputIterator j1, + InputIterator j2); + basic_string &replace(__const_iterator, __const_iterator, + initializer_list); + + size_type copy(charT *s, size_type n, size_type pos = 0) const; + void clear() noexcept; + void swap(basic_string &s) noexcept; + + size_type find(const basic_string &str, size_type pos = 0) const noexcept; + size_type find(const charT *s, size_type pos, size_type n) const; + size_type find(const charT *s, size_type pos = 0) const; + size_type find(charT c, size_type pos = 0) const; + size_type rfind(const basic_string &str, size_type pos = npos) const noexcept; + size_type rfind(const charT *s, size_type pos, size_type n) const; + size_type rfind(const charT *s, size_type pos = npos) const; + size_type rfind(charT c, size_type pos = npos) const; + size_type find_first_of(const basic_string &str, + size_type pos = 0) const noexcept; + size_type find_first_of(const charT *s, size_type pos, size_type n) const; + size_type find_first_of(const charT *s, size_type pos = 0) const; + size_type find_first_of(charT c, size_type pos = 0) const; + size_type find_last_of(const basic_string &str, + size_type pos = npos) const noexcept; + size_type find_last_of(const charT *s, size_type pos, size_type n) const; + size_type find_last_of(const charT *s, size_type pos = npos) const; + size_type find_last_of(charT c, size_type pos = npos) const; + size_type find_first_not_of(const basic_string &str, + size_type pos = 0) const noexcept; + size_type find_first_not_of(const charT *s, size_type pos, size_type n) const; + size_type find_first_not_of(const charT *s, size_type pos = 0) const; + size_type find_first_not_of(charT c, size_type pos = 0) const; + size_type find_last_not_of(const basic_string &str, + + size_type pos = npos) const noexcept; + size_type find_last_not_of(const charT *s, size_type pos, size_type n) const; + size_type find_last_not_of(const charT *s, size_type pos = npos) const; + size_type find_last_not_of(charT c, size_type pos = npos) const; + basic_string substr(size_type pos = 0, size_type n = npos) const; + int compare(const basic_string &str) const noexcept; + int compare(size_type pos1, size_type n1, const basic_string &str) const; + int compare(size_type pos1, size_type n1, const basic_string &str, + size_type pos2, size_type n2 = npos) const; + int compare(const charT *s) const; + int compare(size_type pos1, size_type n1, const charT *s) const; + int compare(size_type pos1, size_type n1, const charT *s, size_type n2) const; +}; + +template +basic_string +operator+(const basic_string &lhs, + const basic_string &rhs); +template +basic_string +operator+(const basic_string &lhs, const charT *rhs); +template +basic_string +operator+(const charT *lhs, const basic_string &rhs); + +template +bool operator==(const basic_string &lhs, + const basic_string &rhs) noexcept; +template +bool operator==(const charT *lhs, + const basic_string &rhs); +template +bool operator==(const basic_string &lhs, + const charT *rhs); +template +bool operator!=(const basic_string &lhs, + const basic_string &rhs) noexcept; +template +bool operator!=(const charT *lhs, + const basic_string &rhs); +template +bool operator!=(const basic_string &lhs, + const charT *rhs); +template +bool operator<(const basic_string &lhs, + const basic_string &rhs) noexcept; +template +bool operator<(const basic_string &lhs, + const charT *rhs); +template +bool operator<(const charT *lhs, + const basic_string &rhs); +template +bool operator>(const basic_string &lhs, + const basic_string &rhs) noexcept; +template +bool operator>(const basic_string &lhs, + const charT *rhs); +template +bool operator>(const charT *lhs, + const basic_string &rhs); +template +bool operator<=(const basic_string &lhs, + const basic_string &rhs) noexcept; +template +bool operator<=(const basic_string &lhs, + const charT *rhs); +template +bool operator<=(const charT *lhs, + const basic_string &rhs); +template +bool operator>=(const basic_string &lhs, + const basic_string &rhs) noexcept; +template +bool operator>=(const basic_string &lhs, + const charT *rhs); +template +bool operator>=(const charT *lhs, + const basic_string &rhs); + +typedef basic_string string; + +int stoi(const string &str, size_t *idx = 0, int base = 10); +long stol(const string &str, size_t *idx = 0, int base = 10); +unsigned long stoul(const string &str, size_t *idx = 0, int base = 10); +long long stoll(const string &str, size_t *idx = 0, int base = 10); +unsigned long long stoull(const string &str, size_t *idx = 0, int base = 10); +float stof(const string &str, size_t *idx = 0); +double stod(const string &str, size_t *idx = 0); +long double stold(const string &str, size_t *idx = 0); + +std::string to_string(int value); +} // namespace std + +#endif // _GHLIBCPP_STRING \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/string.h b/cpp/common/test/includes/standard-library/string.h index f514394688..c4d06b6e7b 100644 --- a/cpp/common/test/includes/standard-library/string.h +++ b/cpp/common/test/includes/standard-library/string.h @@ -1,242 +1,10 @@ -#ifndef _GHLIBCPP_STRING -#define _GHLIBCPP_STRING -#include "errno.h" -#include "initializer_list" -#include "iosfwd.h" -#include "iterator.h" -#include "stddef.h" - -namespace std { -template struct char_traits; - -template class allocator { -public: - allocator() throw(); - typedef size_t size_type; -}; - -template , - class Allocator = allocator> -class basic_string { -public: - using value_type = charT; - using reference = value_type &; - using const_reference = const value_type &; - typedef typename Allocator::size_type size_type; - static const size_type npos = -1; - - basic_string() : basic_string(Allocator()) {} - explicit basic_string(const Allocator &a); - basic_string(const basic_string &str); - basic_string(basic_string &&str) noexcept; - basic_string(const charT *s, size_type n, const Allocator &a = Allocator()); - basic_string(const charT *s, const Allocator &a = Allocator()); - basic_string(size_type n, charT c, const Allocator &a = Allocator()); - template - basic_string(InputIterator begin, InputIterator end, - const Allocator &a = Allocator()); - - ~basic_string(); - basic_string &operator=(const basic_string &str); - basic_string &operator=(basic_string &&str) noexcept; - basic_string &operator=(const charT *s); - basic_string &operator=(charT c); - basic_string &operator=(initializer_list); - - const charT *c_str() const; - charT *data() noexcept; - size_type size() const noexcept; - size_type length() const noexcept; - - typedef __iterator iterator; - typedef __iterator const_iterator; - - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - const_iterator cbegin() const; - const_iterator cend() const; - - const charT &front() const; - charT &front(); - const charT &back() const; - charT &back(); - - const_reference operator[](size_type pos) const; - reference operator[](size_type pos); - const_reference at(size_type n) const; - reference at(size_type n); - basic_string &operator+=(const basic_string &str); - basic_string &operator+=(const charT *s); - basic_string &operator+=(charT c); - basic_string &operator+=(initializer_list); - basic_string &append(const basic_string &str); - basic_string &append(const basic_string &str, size_type pos, - size_type n = npos); - basic_string &append(const charT *s, size_type n); - basic_string &append(const charT *s); - basic_string &append(size_type n, charT c); - template - basic_string &append(InputIterator first, InputIterator last); - basic_string &append(initializer_list); - void push_back(charT c); - basic_string &assign(const basic_string &str); - basic_string &assign(basic_string &&str) noexcept; - basic_string &assign(const basic_string &str, size_type pos, - size_type n = npos); - basic_string &assign(const charT *s, size_type n); - basic_string &assign(const charT *s); - basic_string &assign(size_type n, charT c); - template - basic_string &assign(InputIterator first, InputIterator last); - basic_string &assign(initializer_list); - basic_string &insert(size_type pos1, const basic_string &str); - basic_string &insert(size_type pos1, const basic_string &str, size_type pos2, - size_type n = npos); - basic_string &insert(size_type pos, const charT *s, size_type n); - basic_string &insert(size_type pos, const charT *s); - basic_string &insert(size_type pos, size_type n, charT c); - iterator insert(const_iterator p, charT c); - iterator insert(const_iterator p, size_type n, charT c); - template - iterator insert(const_iterator p, InputIterator first, InputIterator last); - iterator insert(const_iterator p, initializer_list); - basic_string &erase(size_type pos = 0, size_type n = npos); - iterator erase(const_iterator p); - iterator erase(const_iterator first, const_iterator last); - basic_string &replace(size_type pos1, size_type n1, const basic_string &str); - basic_string &replace(size_type pos1, size_type n1, const basic_string &str, - size_type pos2, size_type n2 = npos); - basic_string &replace(size_type pos, size_type n1, const charT *s, - size_type n2); - basic_string &replace(size_type pos, size_type n1, const charT *s); - basic_string &replace(size_type pos, size_type n1, size_type n2, charT c); - basic_string &replace(const_iterator i1, const_iterator i2, - const basic_string &str); - basic_string &replace(const_iterator i1, const_iterator i2, const charT *s, - size_type n); - basic_string &replace(const_iterator i1, const_iterator i2, const charT *s); - basic_string &replace(const_iterator i1, const_iterator i2, size_type n, - charT c); - template - basic_string &replace(const_iterator i1, const_iterator i2, InputIterator j1, - InputIterator j2); - basic_string &replace(const_iterator, const_iterator, - initializer_list); +#ifndef _GHLIBCPP_STRINGH +#define _GHLIBCPP_STRINGH - size_type copy(charT *s, size_type n, size_type pos = 0) const; - void clear() noexcept; - void swap(basic_string &s) noexcept; - - size_type find(const basic_string &str, size_type pos = 0) const noexcept; - size_type find(const charT *s, size_type pos, size_type n) const; - size_type find(const charT *s, size_type pos = 0) const; - size_type find(charT c, size_type pos = 0) const; - size_type rfind(const basic_string &str, size_type pos = npos) const noexcept; - size_type rfind(const charT *s, size_type pos, size_type n) const; - size_type rfind(const charT *s, size_type pos = npos) const; - size_type rfind(charT c, size_type pos = npos) const; - size_type find_first_of(const basic_string &str, - size_type pos = 0) const noexcept; - size_type find_first_of(const charT *s, size_type pos, size_type n) const; - size_type find_first_of(const charT *s, size_type pos = 0) const; - size_type find_first_of(charT c, size_type pos = 0) const; - size_type find_last_of(const basic_string &str, - size_type pos = npos) const noexcept; - size_type find_last_of(const charT *s, size_type pos, size_type n) const; - size_type find_last_of(const charT *s, size_type pos = npos) const; - size_type find_last_of(charT c, size_type pos = npos) const; - size_type find_first_not_of(const basic_string &str, - size_type pos = 0) const noexcept; - size_type find_first_not_of(const charT *s, size_type pos, size_type n) const; - size_type find_first_not_of(const charT *s, size_type pos = 0) const; - size_type find_first_not_of(charT c, size_type pos = 0) const; - size_type find_last_not_of(const basic_string &str, - - size_type pos = npos) const noexcept; - size_type find_last_not_of(const charT *s, size_type pos, size_type n) const; - size_type find_last_not_of(const charT *s, size_type pos = npos) const; - size_type find_last_not_of(charT c, size_type pos = npos) const; - basic_string substr(size_type pos = 0, size_type n = npos) const; - int compare(const basic_string &str) const noexcept; - int compare(size_type pos1, size_type n1, const basic_string &str) const; - int compare(size_type pos1, size_type n1, const basic_string &str, - size_type pos2, size_type n2 = npos) const; - int compare(const charT *s) const; - int compare(size_type pos1, size_type n1, const charT *s) const; - int compare(size_type pos1, size_type n1, const charT *s, size_type n2) const; -}; - -template -basic_string -operator+(const basic_string &lhs, - const basic_string &rhs); -template -basic_string -operator+(const basic_string &lhs, const charT *rhs); -template -basic_string -operator+(const charT *lhs, const basic_string &rhs); - -template -bool operator==(const basic_string &lhs, - const basic_string &rhs) noexcept; -template -bool operator==(const charT *lhs, - const basic_string &rhs); -template -bool operator==(const basic_string &lhs, - const charT *rhs); -template -bool operator!=(const basic_string &lhs, - const basic_string &rhs) noexcept; -template -bool operator!=(const charT *lhs, - const basic_string &rhs); -template -bool operator!=(const basic_string &lhs, - const charT *rhs); -template -bool operator<(const basic_string &lhs, - const basic_string &rhs) noexcept; -template -bool operator<(const basic_string &lhs, - const charT *rhs); -template -bool operator<(const charT *lhs, - const basic_string &rhs); -template -bool operator>(const basic_string &lhs, - const basic_string &rhs) noexcept; -template -bool operator>(const basic_string &lhs, - const charT *rhs); -template -bool operator>(const charT *lhs, - const basic_string &rhs); -template -bool operator<=(const basic_string &lhs, - const basic_string &rhs) noexcept; -template -bool operator<=(const basic_string &lhs, - const charT *rhs); -template -bool operator<=(const charT *lhs, - const basic_string &rhs); -template -bool operator>=(const basic_string &lhs, - const basic_string &rhs) noexcept; -template -bool operator>=(const basic_string &lhs, - const charT *rhs); -template -bool operator>=(const charT *lhs, - const basic_string &rhs); - -typedef basic_string string; +#include "errno.h" typedef unsigned long size_t; + size_t strlen(const char *str); char *strcpy(char *destination, const char *source); char *strncpy(char *destination, const char *source, size_t num); @@ -273,22 +41,6 @@ void *memset(void *dest, int ch, size_t count); void *memmove(void *dest, const void *src, size_t count); int memcmp(const void *lhs, const void *rhs, size_t count); -errno_t memcpy_s(void *dest, rsize_t destsz, const void *src, rsize_t count); -errno_t memmove_s(void *dest, rsize_t destsz, const void *src, rsize_t count); - -int stoi(const string &str, size_t *idx = 0, int base = 10); -long stol(const string &str, size_t *idx = 0, int base = 10); -unsigned long stoul(const string &str, size_t *idx = 0, int base = 10); -long long stoll(const string &str, size_t *idx = 0, int base = 10); -unsigned long long stoull(const string &str, size_t *idx = 0, int base = 10); -float stof(const string &str, size_t *idx = 0); -double stod(const string &str, size_t *idx = 0); -long double stold(const string &str, size_t *idx = 0); - -std::string to_string(int value); -} // namespace std - -std::errno_t memset_s(void *dest, rsize_t destsz, int ch, rsize_t count); size_t strlen(const char *str); -#endif // _GHLIBCPP_STRING \ No newline at end of file +#endif // _GHLIBCPP_STRINGH \ No newline at end of file diff --git a/cpp/common/test/includes/standard-library/vector.h b/cpp/common/test/includes/standard-library/vector.h index caa443f641..6d0293f8f5 100644 --- a/cpp/common/test/includes/standard-library/vector.h +++ b/cpp/common/test/includes/standard-library/vector.h @@ -1,7 +1,7 @@ #ifndef _GHLIBCPP_VECTOR #define _GHLIBCPP_VECTOR -#include "iterator.h" -#include "string.h" +#include +#include namespace std { diff --git a/cpp/common/test/rules/basicstringmaynotbenullterminated/test.cpp b/cpp/common/test/rules/basicstringmaynotbenullterminated/test.cpp index e903a933af..973a7a4ad1 100644 --- a/cpp/common/test/rules/basicstringmaynotbenullterminated/test.cpp +++ b/cpp/common/test/rules/basicstringmaynotbenullterminated/test.cpp @@ -1,6 +1,6 @@ #include +#include #include -#include void f1() { char a1[7] = "CodeQL"; diff --git a/cpp/common/test/rules/donotdestroyamutexwhileitislocked/DoNotDestroyAMutexWhileItIsLocked.expected b/cpp/common/test/rules/donotdestroyamutexwhileitislocked/DoNotDestroyAMutexWhileItIsLocked.expected index 0ae4aafa66..71ccc11ba7 100644 --- a/cpp/common/test/rules/donotdestroyamutexwhileitislocked/DoNotDestroyAMutexWhileItIsLocked.expected +++ b/cpp/common/test/rules/donotdestroyamutexwhileitislocked/DoNotDestroyAMutexWhileItIsLocked.expected @@ -1,6 +1,3 @@ -| test.cpp:4:18:4:33 | call to mutex | Mutex used by thread potentially $@ while in use. | test.cpp:11:18:11:26 | call to ~mutex | destroyed | | test.cpp:4:18:4:33 | call to mutex | Mutex used by thread potentially $@ while in use. | test.cpp:11:18:11:26 | delete | destroyed | -| test.cpp:16:14:16:15 | call to mutex | Mutex used by thread potentially $@ while in use. | test.cpp:21:1:21:1 | call to ~mutex | destroyed | | test.cpp:16:14:16:15 | call to mutex | Mutex used by thread potentially $@ while in use. | test.cpp:21:1:21:1 | return ... | destroyed | -| test.cpp:94:8:94:23 | call to mutex | Mutex used by thread potentially $@ while in use. | test.cpp:10:34:10:42 | call to ~mutex | destroyed | | test.cpp:94:8:94:23 | call to mutex | Mutex used by thread potentially $@ while in use. | test.cpp:10:34:10:42 | delete | destroyed | diff --git a/cpp/common/test/rules/informationleakageacrossboundaries/InformationLeakageAcrossBoundaries.expected b/cpp/common/test/rules/informationleakageacrossboundaries/InformationLeakageAcrossBoundaries.expected index 38fcaf61be..d7a7659f07 100644 --- a/cpp/common/test/rules/informationleakageacrossboundaries/InformationLeakageAcrossBoundaries.expected +++ b/cpp/common/test/rules/informationleakageacrossboundaries/InformationLeakageAcrossBoundaries.expected @@ -15,6 +15,6 @@ | test.cpp:43:12:43:12 | s | 's' may leak information from {x (test.cpp:7)}. Path: s (test.cpp:43) --> & ... (test.cpp:47) | | test.cpp:58:12:58:12 | s | 's' may leak information from {x (test.cpp:7), y (test.cpp:8)}. Path: s (test.cpp:58) --> & ... (test.cpp:59) | | test.cpp:64:12:64:12 | s | 's' may leak information from {y (test.cpp:8)}. Path: s (test.cpp:64) --> & ... (test.cpp:66) | -| test.cpp:112:16:112:16 | s | 's' may leak information from {buf (test.cpp:92)}. Path: s (test.cpp:112) --> & ... (test.cpp:115) | -| test.cpp:128:12:128:12 | s | 's' may leak information from {x (test.cpp:7), y (test.cpp:8)}. Path: s (test.cpp:128) --> & ... (test.cpp:132) | -| test.cpp:157:22:157:22 | s | 's' may leak information from {2 to 2 bytes of padding in has_padding (test.cpp:151)}. Path: s (test.cpp:157) --> & ... (test.cpp:160) | +| test.cpp:110:16:110:16 | s | 's' may leak information from {buf (test.cpp:92)}. Path: s (test.cpp:110) --> & ... (test.cpp:113) | +| test.cpp:126:12:126:12 | s | 's' may leak information from {x (test.cpp:7), y (test.cpp:8)}. Path: s (test.cpp:126) --> & ... (test.cpp:130) | +| test.cpp:155:22:155:22 | s | 's' may leak information from {2 to 2 bytes of padding in has_padding (test.cpp:149)}. Path: s (test.cpp:155) --> & ... (test.cpp:158) | diff --git a/cpp/common/test/rules/informationleakageacrossboundaries/interprocedural.cpp b/cpp/common/test/rules/informationleakageacrossboundaries/interprocedural.cpp index 15e8b81682..016d40baeb 100644 --- a/cpp/common/test/rules/informationleakageacrossboundaries/interprocedural.cpp +++ b/cpp/common/test/rules/informationleakageacrossboundaries/interprocedural.cpp @@ -1,5 +1,5 @@ +#include #include -#include unsigned long copy_to_user(void *to, const void *from, unsigned long n); diff --git a/cpp/common/test/rules/informationleakageacrossboundaries/multilayer.cpp b/cpp/common/test/rules/informationleakageacrossboundaries/multilayer.cpp index 2298895de1..c5a9d29e0f 100644 --- a/cpp/common/test/rules/informationleakageacrossboundaries/multilayer.cpp +++ b/cpp/common/test/rules/informationleakageacrossboundaries/multilayer.cpp @@ -1,5 +1,5 @@ +#include #include -#include unsigned long copy_to_user(void *to, const void *from, unsigned long n); diff --git a/cpp/common/test/rules/informationleakageacrossboundaries/test.cpp b/cpp/common/test/rules/informationleakageacrossboundaries/test.cpp index 3b68ffbd86..9a5fe40ef8 100644 --- a/cpp/common/test/rules/informationleakageacrossboundaries/test.cpp +++ b/cpp/common/test/rules/informationleakageacrossboundaries/test.cpp @@ -1,5 +1,5 @@ +#include #include -#include unsigned long copy_to_user(void *to, const void *from, unsigned long n); @@ -106,8 +106,6 @@ void zero_array_by_ref() { copy_to_user(0, &s, sizeof s); // COMPLIANT } -char *strcpy(char *dst, const char *src); - void use_strcpy() { PascalString s; strcpy(s.buf, "Hello, World"); // does not zero rest of s.buf diff --git a/cpp/common/test/rules/memcmpusedtocomparepaddingdata/test.cpp b/cpp/common/test/rules/memcmpusedtocomparepaddingdata/test.cpp index 9f0ba8cab7..7d004a2a39 100644 --- a/cpp/common/test/rules/memcmpusedtocomparepaddingdata/test.cpp +++ b/cpp/common/test/rules/memcmpusedtocomparepaddingdata/test.cpp @@ -1,4 +1,4 @@ -#include +#include struct S1 { unsigned char buffType; diff --git a/cpp/common/test/rules/operationmaynotnullterminatecstylestring/test.cpp b/cpp/common/test/rules/operationmaynotnullterminatecstylestring/test.cpp index 1b35da9174..7e93427905 100644 --- a/cpp/common/test/rules/operationmaynotnullterminatecstylestring/test.cpp +++ b/cpp/common/test/rules/operationmaynotnullterminatecstylestring/test.cpp @@ -1,7 +1,7 @@ #pragma clang diagnostic ignored "-Wfortify-source" #include +#include #include -#include void f1() { char a1[7] = "CodeQL"; diff --git a/cpp/common/test/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.expected b/cpp/common/test/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.expected index a4f85ecb72..d5d138ec19 100644 --- a/cpp/common/test/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.expected +++ b/cpp/common/test/rules/ownedpointervaluestoredinunrelatedsmartpointer/OwnedPointerValueStoredInUnrelatedSmartPointer.expected @@ -6,7 +6,6 @@ problems | test.cpp:12:28:12:29 | v2 | test.cpp:10:8:10:17 | new | test.cpp:12:28:12:29 | v2 | Raw pointer flows to initialize multiple unrelated smart pointers. | | test.cpp:17:27:17:28 | v1 | test.cpp:16:13:16:22 | new | test.cpp:17:27:17:28 | v1 | Raw pointer flows to initialize multiple unrelated smart pointers. | edges -| ../../includes/standard-library/memory.h:76:17:76:19 | ptr | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | | test.cpp:3:14:3:15 | v1 | test.cpp:5:27:5:28 | v1 | | test.cpp:3:14:3:15 | v1 | test.cpp:6:31:6:33 | call to get | | test.cpp:3:14:3:15 | v1 | test.cpp:7:28:7:29 | v2 | @@ -14,21 +13,11 @@ edges | test.cpp:5:27:5:29 | call to shared_ptr | test.cpp:6:31:6:33 | call to get | | test.cpp:8:8:8:14 | 0 | test.cpp:9:28:9:29 | v2 | | test.cpp:10:8:10:17 | new | test.cpp:11:28:11:29 | v2 | -| test.cpp:10:8:10:17 | new | test.cpp:11:28:11:29 | v2 | | test.cpp:10:8:10:17 | new | test.cpp:12:28:12:29 | v2 | -| test.cpp:11:28:11:29 | ref arg v2 | test.cpp:12:28:12:29 | v2 | -| test.cpp:11:28:11:29 | v2 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | -| test.cpp:11:28:11:29 | v2 | test.cpp:11:28:11:29 | ref arg v2 | -| test.cpp:16:13:16:22 | new | test.cpp:17:27:17:28 | v1 | | test.cpp:16:13:16:22 | new | test.cpp:17:27:17:28 | v1 | | test.cpp:16:13:16:22 | new | test.cpp:19:6:19:7 | v1 | -| test.cpp:17:27:17:28 | ref arg v1 | test.cpp:19:6:19:7 | v1 | -| test.cpp:17:27:17:28 | v1 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | -| test.cpp:17:27:17:28 | v1 | test.cpp:17:27:17:28 | ref arg v1 | | test.cpp:19:6:19:7 | v1 | test.cpp:3:14:3:15 | v1 | nodes -| ../../includes/standard-library/memory.h:76:17:76:19 | ptr | semmle.label | ptr | -| ../../includes/standard-library/memory.h:76:17:76:19 | ptr | semmle.label | ptr | | test.cpp:3:14:3:15 | v1 | semmle.label | v1 | | test.cpp:4:13:4:14 | v1 | semmle.label | v1 | | test.cpp:5:27:5:28 | v1 | semmle.label | v1 | @@ -38,15 +27,9 @@ nodes | test.cpp:8:8:8:14 | 0 | semmle.label | 0 | | test.cpp:9:28:9:29 | v2 | semmle.label | v2 | | test.cpp:10:8:10:17 | new | semmle.label | new | -| test.cpp:11:28:11:29 | ref arg v2 | semmle.label | ref arg v2 | -| test.cpp:11:28:11:29 | v2 | semmle.label | v2 | | test.cpp:11:28:11:29 | v2 | semmle.label | v2 | | test.cpp:12:28:12:29 | v2 | semmle.label | v2 | | test.cpp:16:13:16:22 | new | semmle.label | new | -| test.cpp:17:27:17:28 | ref arg v1 | semmle.label | ref arg v1 | -| test.cpp:17:27:17:28 | v1 | semmle.label | v1 | | test.cpp:17:27:17:28 | v1 | semmle.label | v1 | | test.cpp:19:6:19:7 | v1 | semmle.label | v1 | subpaths -| test.cpp:11:28:11:29 | v2 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | test.cpp:11:28:11:29 | ref arg v2 | -| test.cpp:17:27:17:28 | v1 | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | ../../includes/standard-library/memory.h:76:17:76:19 | ptr | test.cpp:17:27:17:28 | ref arg v1 | diff --git a/cpp/common/test/rules/preprocessingdirectivewithinmacroargument/test.cpp b/cpp/common/test/rules/preprocessingdirectivewithinmacroargument/test.cpp index a70d631041..f58cb4a442 100644 --- a/cpp/common/test/rules/preprocessingdirectivewithinmacroargument/test.cpp +++ b/cpp/common/test/rules/preprocessingdirectivewithinmacroargument/test.cpp @@ -1,4 +1,4 @@ -#include +#include #define MACROFUNCTION(X) std::strlen(X) void f() {